{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "RootConfig",
  "description": "Application configuration root",
  "type": "object",
  "required": [
    "matrix",
    "secrets"
  ],
  "properties": {
    "clients": {
      "description": "List of OAuth 2.0/OIDC clients config",
      "type": "array",
      "items": {
        "$ref": "#/definitions/ClientConfig"
      }
    },
    "http": {
      "description": "Configuration of the HTTP server",
      "default": {
        "listeners": [
          {
            "name": "web",
            "resources": [
              {
                "name": "discovery"
              },
              {
                "name": "human"
              },
              {
                "name": "oauth"
              },
              {
                "name": "compat"
              },
              {
                "name": "graphql"
              },
              {
                "name": "assets"
              }
            ],
            "binds": [
              {
                "address": "[::]:8080"
              }
            ],
            "proxy_protocol": false
          },
          {
            "name": "internal",
            "resources": [
              {
                "name": "health"
              }
            ],
            "binds": [
              {
                "host": "localhost",
                "port": 8081
              }
            ],
            "proxy_protocol": false
          }
        ],
        "trusted_proxies": [
          "192.168.0.0/16",
          "172.16.0.0/12",
          "10.0.0.0/10",
          "127.0.0.1/8",
          "fd00::/8",
          "::1/128"
        ],
        "public_base": "http://[::]:8080/",
        "issuer": "http://[::]:8080/"
      },
      "allOf": [
        {
          "$ref": "#/definitions/HttpConfig"
        }
      ]
    },
    "database": {
      "description": "Database connection configuration",
      "default": {
        "uri": "postgresql://",
        "max_connections": 10,
        "min_connections": 0,
        "connect_timeout": 30,
        "idle_timeout": 600,
        "max_lifetime": 1800
      },
      "allOf": [
        {
          "$ref": "#/definitions/DatabaseConfig"
        }
      ]
    },
    "telemetry": {
      "description": "Configuration related to sending monitoring data",
      "allOf": [
        {
          "$ref": "#/definitions/TelemetryConfig"
        }
      ]
    },
    "templates": {
      "description": "Configuration related to templates",
      "allOf": [
        {
          "$ref": "#/definitions/TemplatesConfig"
        }
      ]
    },
    "email": {
      "description": "Configuration related to sending emails",
      "default": {
        "from": "\"Authentication Service\" <root@localhost>",
        "reply_to": "\"Authentication Service\" <root@localhost>",
        "transport": "blackhole"
      },
      "allOf": [
        {
          "$ref": "#/definitions/EmailConfig"
        }
      ]
    },
    "secrets": {
      "description": "Application secrets",
      "allOf": [
        {
          "$ref": "#/definitions/SecretsConfig"
        }
      ]
    },
    "passwords": {
      "description": "Configuration related to user passwords",
      "default": {
        "enabled": true,
        "schemes": [
          {
            "version": 1,
            "algorithm": "argon2id"
          }
        ],
        "minimum_complexity": 3
      },
      "allOf": [
        {
          "$ref": "#/definitions/PasswordsConfig"
        }
      ]
    },
    "matrix": {
      "description": "Configuration related to the homeserver",
      "allOf": [
        {
          "$ref": "#/definitions/MatrixConfig"
        }
      ]
    },
    "policy": {
      "description": "Configuration related to the OPA policies",
      "allOf": [
        {
          "$ref": "#/definitions/PolicyConfig"
        }
      ]
    },
    "rate_limiting": {
      "description": "Configuration related to limiting the rate of user actions to prevent abuse",
      "allOf": [
        {
          "$ref": "#/definitions/RateLimitingConfig"
        }
      ]
    },
    "upstream_oauth2": {
      "description": "Configuration related to upstream OAuth providers",
      "allOf": [
        {
          "$ref": "#/definitions/UpstreamOAuth2Config"
        }
      ]
    },
    "branding": {
      "description": "Configuration section for tweaking the branding of the service",
      "allOf": [
        {
          "$ref": "#/definitions/BrandingConfig"
        }
      ]
    },
    "captcha": {
      "description": "Configuration section to setup CAPTCHA protection on a few operations",
      "allOf": [
        {
          "$ref": "#/definitions/CaptchaConfig"
        }
      ]
    },
    "account": {
      "description": "Configuration section to configure features related to account management",
      "allOf": [
        {
          "$ref": "#/definitions/AccountConfig"
        }
      ]
    },
    "experimental": {
      "description": "Experimental configuration options",
      "allOf": [
        {
          "$ref": "#/definitions/ExperimentalConfig"
        }
      ]
    }
  },
  "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",
          "type": "string",
          "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$"
        },
        "client_auth_method": {
          "description": "Authentication method used for this client",
          "allOf": [
            {
              "$ref": "#/definitions/ClientAuthMethodConfig"
            }
          ]
        },
        "client_name": {
          "description": "Name of the `OAuth2` client",
          "type": "string"
        },
        "client_secret": {
          "description": "The client secret, used by the `client_secret_basic`, `client_secret_post` and `client_secret_jwt` authentication methods",
          "type": "string"
        },
        "jwks": {
          "description": "The JSON Web Key Set (JWKS) used by the `private_key_jwt` authentication method. Mutually exclusive with `jwks_uri`",
          "allOf": [
            {
              "$ref": "#/definitions/JsonWebKeySet_for_JsonWebKeyPublicParameters"
            }
          ]
        },
        "jwks_uri": {
          "description": "The URL of the JSON Web Key Set (JWKS) used by the `private_key_jwt` authentication method. Mutually exclusive with `jwks`",
          "type": "string",
          "format": "uri"
        },
        "redirect_uris": {
          "description": "List of allowed redirect URIs",
          "type": "array",
          "items": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    },
    "ClientAuthMethodConfig": {
      "description": "Authentication method used by clients",
      "oneOf": [
        {
          "description": "`none`: No authentication",
          "type": "string",
          "enum": [
            "none"
          ]
        },
        {
          "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic authorization credentials",
          "type": "string",
          "enum": [
            "client_secret_basic"
          ]
        },
        {
          "description": "`client_secret_post`: `client_id` and `client_secret` sent in the request body",
          "type": "string",
          "enum": [
            "client_secret_post"
          ]
        },
        {
          "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed using the `client_secret`",
          "type": "string",
          "enum": [
            "client_secret_jwt"
          ]
        },
        {
          "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed by an asymmetric key",
          "type": "string",
          "enum": [
            "private_key_jwt"
          ]
        }
      ]
    },
    "JsonWebKeySet_for_JsonWebKeyPublicParameters": {
      "type": "object",
      "required": [
        "keys"
      ],
      "properties": {
        "keys": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/JsonWebKey_for_JsonWebKeyPublicParameters"
          }
        }
      }
    },
    "JsonWebKey_for_JsonWebKeyPublicParameters": {
      "type": "object",
      "oneOf": [
        {
          "type": "object",
          "required": [
            "e",
            "kty",
            "n"
          ],
          "properties": {
            "kty": {
              "type": "string",
              "enum": [
                "RSA"
              ]
            },
            "n": {
              "type": "string"
            },
            "e": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "crv",
            "kty",
            "x",
            "y"
          ],
          "properties": {
            "kty": {
              "type": "string",
              "enum": [
                "EC"
              ]
            },
            "crv": {
              "$ref": "#/definitions/JsonWebKeyEcEllipticCurve"
            },
            "x": {
              "type": "string"
            },
            "y": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "crv",
            "kty",
            "x"
          ],
          "properties": {
            "kty": {
              "type": "string",
              "enum": [
                "OKP"
              ]
            },
            "crv": {
              "$ref": "#/definitions/JsonWebKeyOkpEllipticCurve"
            },
            "x": {
              "type": "string"
            }
          }
        }
      ],
      "properties": {
        "use": {
          "$ref": "#/definitions/JsonWebKeyUse"
        },
        "key_ops": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/JsonWebKeyOperation"
          }
        },
        "alg": {
          "$ref": "#/definitions/JsonWebSignatureAlg"
        },
        "kid": {
          "type": "string"
        },
        "x5u": {
          "type": "string"
        },
        "x5c": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "x5t": {
          "type": "string"
        },
        "x5t#S256": {
          "type": "string"
        }
      }
    },
    "JsonWebKeyUse": {
      "description": "JSON Web Key Use",
      "anyOf": [
        {
          "description": "Digital Signature or MAC",
          "const": "sig"
        },
        {
          "description": "Encryption",
          "const": "enc"
        }
      ]
    },
    "JsonWebKeyOperation": {
      "description": "JSON Web Key Operation",
      "anyOf": [
        {
          "description": "Compute digital signature or MAC",
          "const": "sign"
        },
        {
          "description": "Verify digital signature or MAC",
          "const": "verify"
        },
        {
          "description": "Encrypt content",
          "const": "encrypt"
        },
        {
          "description": "Decrypt content and validate decryption, if applicable",
          "const": "decrypt"
        },
        {
          "description": "Encrypt key",
          "const": "wrapKey"
        },
        {
          "description": "Decrypt key and validate decryption, if applicable",
          "const": "unwrapKey"
        },
        {
          "description": "Derive key",
          "const": "deriveKey"
        },
        {
          "description": "Derive bits not to be used as a key",
          "const": "deriveBits"
        }
      ]
    },
    "JsonWebSignatureAlg": {
      "description": "JSON Web Signature \"alg\" parameter",
      "anyOf": [
        {
          "description": "HMAC using SHA-256",
          "const": "HS256"
        },
        {
          "description": "HMAC using SHA-384",
          "const": "HS384"
        },
        {
          "description": "HMAC using SHA-512",
          "const": "HS512"
        },
        {
          "description": "RSASSA-PKCS1-v1_5 using SHA-256",
          "const": "RS256"
        },
        {
          "description": "RSASSA-PKCS1-v1_5 using SHA-384",
          "const": "RS384"
        },
        {
          "description": "RSASSA-PKCS1-v1_5 using SHA-512",
          "const": "RS512"
        },
        {
          "description": "ECDSA using P-256 and SHA-256",
          "const": "ES256"
        },
        {
          "description": "ECDSA using P-384 and SHA-384",
          "const": "ES384"
        },
        {
          "description": "ECDSA using P-521 and SHA-512",
          "const": "ES512"
        },
        {
          "description": "RSASSA-PSS using SHA-256 and MGF1 with SHA-256",
          "const": "PS256"
        },
        {
          "description": "RSASSA-PSS using SHA-384 and MGF1 with SHA-384",
          "const": "PS384"
        },
        {
          "description": "RSASSA-PSS using SHA-512 and MGF1 with SHA-512",
          "const": "PS512"
        },
        {
          "description": "No digital signature or MAC performed",
          "const": "none"
        },
        {
          "description": "EdDSA signature algorithms",
          "const": "EdDSA"
        },
        {
          "description": "ECDSA using secp256k1 curve and SHA-256",
          "const": "ES256K"
        }
      ]
    },
    "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"
          }
        },
        "trusted_proxies": {
          "description": "List of trusted reverse proxies that can set the `X-Forwarded-For` header",
          "default": [
            "192.168.0.0/16",
            "172.16.0.0/12",
            "10.0.0.0/10",
            "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",
          "type": "string",
          "format": "uri"
        },
        "issuer": {
          "description": "OIDC issuer URL. Defaults to `public_base` if not set.",
          "type": "string",
          "format": "uri"
        }
      }
    },
    "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"
        },
        "resources": {
          "description": "List of resources to mount",
          "type": "array",
          "items": {
            "$ref": "#/definitions/Resource"
          }
        },
        "prefix": {
          "description": "HTTP prefix to mount the resources on",
          "type": "string"
        },
        "binds": {
          "description": "List of sockets to bind",
          "type": "array",
          "items": {
            "$ref": "#/definitions/BindConfig"
          }
        },
        "proxy_protocol": {
          "description": "Accept `HAProxy`'s Proxy Protocol V1",
          "default": false,
          "type": "boolean"
        },
        "tls": {
          "description": "If set, makes the listener use TLS with the provided certificate and key",
          "allOf": [
            {
              "$ref": "#/definitions/TlsConfig"
            }
          ]
        }
      }
    },
    "Resource": {
      "description": "HTTP resources to mount",
      "oneOf": [
        {
          "description": "Healthcheck endpoint (/health)",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "health"
              ]
            }
          }
        },
        {
          "description": "Prometheus metrics endpoint (/metrics)",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "prometheus"
              ]
            }
          }
        },
        {
          "description": "OIDC discovery endpoints",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "discovery"
              ]
            }
          }
        },
        {
          "description": "Pages destined to be viewed by humans",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "human"
              ]
            }
          }
        },
        {
          "description": "GraphQL endpoint",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "graphql"
              ]
            },
            "playground": {
              "description": "Enabled the GraphQL playground",
              "type": "boolean"
            },
            "undocumented_oauth2_access": {
              "description": "Allow access for OAuth 2.0 clients (undocumented)",
              "type": "boolean"
            }
          }
        },
        {
          "description": "OAuth-related APIs",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "oauth"
              ]
            }
          }
        },
        {
          "description": "Matrix compatibility API",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "compat"
              ]
            }
          }
        },
        {
          "description": "Static files",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "assets"
              ]
            },
            "path": {
              "description": "Path to the directory to serve.",
              "type": "string"
            }
          }
        },
        {
          "description": "Admin API, served at `/api/admin/v1`",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "adminapi"
              ]
            }
          }
        },
        {
          "description": "Mount a \"/connection-info\" handler which helps debugging informations on the upstream connection",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "connection-info"
              ]
            }
          }
        }
      ]
    },
    "BindConfig": {
      "description": "Configuration of a single listener",
      "anyOf": [
        {
          "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"
            },
            "port": {
              "description": "Port on which to listen.",
              "type": "integer",
              "format": "uint16",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Listen on the specified address",
          "type": "object",
          "required": [
            "address"
          ],
          "properties": {
            "address": {
              "description": "Host and port on which to listen",
              "examples": [
                "[::1]:8080",
                "[::]:8080",
                "127.0.0.1:8080",
                "0.0.0.0:8080"
              ],
              "type": "string"
            }
          }
        },
        {
          "description": "Listen on a UNIX domain socket",
          "type": "object",
          "required": [
            "socket"
          ],
          "properties": {
            "socket": {
              "description": "Path to the socket",
              "type": "string"
            }
          }
        },
        {
          "description": "Accept connections on file descriptors passed by the parent process.\n\nThis is useful for grabbing sockets passed by systemd.\n\nSee <https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html>",
          "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,
              "type": "integer",
              "format": "uint",
              "minimum": 0.0
            },
            "kind": {
              "description": "Whether the socket is a TCP socket or a UNIX domain socket. Defaults to TCP.",
              "default": "tcp",
              "allOf": [
                {
                  "$ref": "#/definitions/UnixOrTcp"
                }
              ]
            }
          }
        }
      ]
    },
    "UnixOrTcp": {
      "description": "Kind of socket",
      "oneOf": [
        {
          "description": "UNIX domain socket",
          "type": "string",
          "enum": [
            "unix"
          ]
        },
        {
          "description": "TCP socket",
          "type": "string",
          "enum": [
            "tcp"
          ]
        }
      ]
    },
    "TlsConfig": {
      "description": "Configuration related to TLS on a listener",
      "type": "object",
      "properties": {
        "certificate": {
          "description": "PEM-encoded X509 certificate chain\n\nExactly one of `certificate` or `certificate_file` must be set.",
          "type": "string"
        },
        "certificate_file": {
          "description": "File containing the PEM-encoded X509 certificate chain\n\nExactly one of `certificate` or `certificate_file` must be set.",
          "type": "string"
        },
        "key": {
          "description": "PEM-encoded private key\n\nExactly one of `key` or `key_file` must be set.",
          "type": "string"
        },
        "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"
        },
        "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"
        },
        "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"
        }
      }
    },
    "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://",
          "type": "string",
          "format": "uri"
        },
        "host": {
          "description": "Name of host to connect to\n\nThis must not be specified if `uri` is specified.",
          "allOf": [
            {
              "$ref": "#/definitions/Hostname"
            }
          ]
        },
        "port": {
          "description": "Port number to connect at the server host\n\nThis must not be specified if `uri` is specified.",
          "type": "integer",
          "format": "uint16",
          "maximum": 65535.0,
          "minimum": 1.0
        },
        "socket": {
          "description": "Directory containing the UNIX socket to connect to\n\nThis must not be specified if `uri` is specified.",
          "type": "string"
        },
        "username": {
          "description": "PostgreSQL user name to connect as\n\nThis must not be specified if `uri` is specified.",
          "type": "string"
        },
        "password": {
          "description": "Password to be used if the server demands password authentication\n\nThis must not be specified if `uri` is specified.",
          "type": "string"
        },
        "database": {
          "description": "The database name\n\nThis must not be specified if `uri` is specified.",
          "type": "string"
        },
        "ssl_mode": {
          "description": "How to handle SSL connections",
          "allOf": [
            {
              "$ref": "#/definitions/PgSslMode"
            }
          ]
        },
        "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"
        },
        "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"
        },
        "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"
        },
        "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"
        },
        "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"
        },
        "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"
        },
        "max_connections": {
          "description": "Set the maximum number of connections the pool should maintain",
          "default": 10,
          "type": "integer",
          "format": "uint32",
          "minimum": 1.0
        },
        "min_connections": {
          "description": "Set the minimum number of connections the pool should maintain",
          "default": 0,
          "type": "integer",
          "format": "uint32",
          "minimum": 0.0
        },
        "connect_timeout": {
          "description": "Set the amount of time to attempt connecting to the database",
          "default": 30,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "idle_timeout": {
          "description": "Set a maximum idle duration for individual connections",
          "default": 600,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "max_lifetime": {
          "description": "Set the maximum lifetime of individual connections",
          "default": 1800,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        }
      }
    },
    "Hostname": {
      "type": "string",
      "format": "hostname"
    },
    "PgSslMode": {
      "description": "Options for controlling the level of protection provided for PostgreSQL SSL connections.",
      "oneOf": [
        {
          "description": "Only try a non-SSL connection.",
          "type": "string",
          "enum": [
            "disable"
          ]
        },
        {
          "description": "First try a non-SSL connection; if that fails, try an SSL connection.",
          "type": "string",
          "enum": [
            "allow"
          ]
        },
        {
          "description": "First try an SSL connection; if that fails, try a non-SSL connection.",
          "type": "string",
          "enum": [
            "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.",
          "type": "string",
          "enum": [
            "require"
          ]
        },
        {
          "description": "Only try an SSL connection, and verify that the server certificate is issued by a trusted certificate authority (CA).",
          "type": "string",
          "enum": [
            "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.",
          "type": "string",
          "enum": [
            "verify-full"
          ]
        }
      ]
    },
    "TelemetryConfig": {
      "description": "Configuration related to sending monitoring data",
      "type": "object",
      "properties": {
        "tracing": {
          "description": "Configuration related to exporting traces",
          "allOf": [
            {
              "$ref": "#/definitions/TracingConfig"
            }
          ]
        },
        "metrics": {
          "description": "Configuration related to exporting metrics",
          "allOf": [
            {
              "$ref": "#/definitions/MetricsConfig"
            }
          ]
        },
        "sentry": {
          "description": "Configuration related to the Sentry integration",
          "allOf": [
            {
              "$ref": "#/definitions/SentryConfig"
            }
          ]
        }
      }
    },
    "TracingConfig": {
      "description": "Configuration related to exporting traces",
      "type": "object",
      "properties": {
        "exporter": {
          "description": "Exporter to use when exporting traces",
          "default": "none",
          "allOf": [
            {
              "$ref": "#/definitions/TracingExporterKind"
            }
          ]
        },
        "endpoint": {
          "description": "OTLP exporter: OTLP over HTTP compatible endpoint",
          "default": "https://localhost:4318",
          "type": "string",
          "format": "uri"
        },
        "propagators": {
          "description": "List of propagation formats to use for incoming and outgoing requests",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/Propagator"
          }
        },
        "sample_rate": {
          "description": "Sample rate for traces\n\nDefaults to `1.0` if not set.",
          "examples": [
            0.5
          ],
          "type": "number",
          "format": "double",
          "maximum": 1.0,
          "minimum": 0.0
        }
      }
    },
    "TracingExporterKind": {
      "description": "Exporter to use when exporting traces",
      "oneOf": [
        {
          "description": "Don't export traces",
          "type": "string",
          "enum": [
            "none"
          ]
        },
        {
          "description": "Export traces to the standard output. Only useful for debugging",
          "type": "string",
          "enum": [
            "stdout"
          ]
        },
        {
          "description": "Export traces to an OpenTelemetry protocol compatible endpoint",
          "type": "string",
          "enum": [
            "otlp"
          ]
        }
      ]
    },
    "Propagator": {
      "description": "Propagation format for incoming and outgoing requests",
      "oneOf": [
        {
          "description": "Propagate according to the W3C Trace Context specification",
          "type": "string",
          "enum": [
            "tracecontext"
          ]
        },
        {
          "description": "Propagate according to the W3C Baggage specification",
          "type": "string",
          "enum": [
            "baggage"
          ]
        },
        {
          "description": "Propagate trace context with Jaeger compatible headers",
          "type": "string",
          "enum": [
            "jaeger"
          ]
        }
      ]
    },
    "MetricsConfig": {
      "description": "Configuration related to exporting metrics",
      "type": "object",
      "properties": {
        "exporter": {
          "description": "Exporter to use when exporting metrics",
          "default": "none",
          "allOf": [
            {
              "$ref": "#/definitions/MetricsExporterKind"
            }
          ]
        },
        "endpoint": {
          "description": "OTLP exporter: OTLP over HTTP compatible endpoint",
          "default": "https://localhost:4318",
          "type": "string",
          "format": "uri"
        }
      }
    },
    "MetricsExporterKind": {
      "description": "Exporter to use when exporting metrics",
      "oneOf": [
        {
          "description": "Don't export metrics",
          "type": "string",
          "enum": [
            "none"
          ]
        },
        {
          "description": "Export metrics to stdout. Only useful for debugging",
          "type": "string",
          "enum": [
            "stdout"
          ]
        },
        {
          "description": "Export metrics to an OpenTelemetry protocol compatible endpoint",
          "type": "string",
          "enum": [
            "otlp"
          ]
        },
        {
          "description": "Export metrics via Prometheus. An HTTP listener with the `prometheus` resource must be setup to expose the Promethes metrics.",
          "type": "string",
          "enum": [
            "prometheus"
          ]
        }
      ]
    },
    "SentryConfig": {
      "description": "Configuration related to the Sentry integration",
      "type": "object",
      "properties": {
        "dsn": {
          "description": "Sentry DSN",
          "examples": [
            "https://public@host:port/1"
          ],
          "type": "string",
          "format": "uri"
        },
        "environment": {
          "description": "Environment to use when sending events to Sentry\n\nDefaults to `production` if not set.",
          "examples": [
            "production"
          ],
          "type": "string"
        },
        "sample_rate": {
          "description": "Sample rate for event submissions\n\nDefaults to `1.0` if not set.",
          "examples": [
            0.5
          ],
          "type": "number",
          "format": "float",
          "maximum": 1.0,
          "minimum": 0.0
        },
        "traces_sample_rate": {
          "description": "Sample rate for tracing transactions\n\nDefaults to `0.0` if not set.",
          "examples": [
            0.5
          ],
          "type": "number",
          "format": "float",
          "maximum": 1.0,
          "minimum": 0.0
        }
      }
    },
    "TemplatesConfig": {
      "description": "Configuration related to templates",
      "type": "object",
      "properties": {
        "path": {
          "description": "Path to the folder which holds the templates",
          "type": "string"
        },
        "assets_manifest": {
          "description": "Path to the assets manifest",
          "type": "string"
        },
        "translations_path": {
          "description": "Path to the translations",
          "type": "string"
        }
      }
    },
    "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\" <root@localhost>",
          "type": "string",
          "format": "email"
        },
        "reply_to": {
          "description": "Email address to use as Reply-To when sending emails",
          "default": "\"Authentication Service\" <root@localhost>",
          "type": "string",
          "format": "email"
        },
        "transport": {
          "description": "What backend should be used when sending emails",
          "allOf": [
            {
              "$ref": "#/definitions/EmailTransportKind"
            }
          ]
        },
        "mode": {
          "description": "SMTP transport: Connection mode to the relay",
          "allOf": [
            {
              "$ref": "#/definitions/EmailSmtpMode"
            }
          ]
        },
        "hostname": {
          "description": "SMTP transport: Hostname to connect to",
          "allOf": [
            {
              "$ref": "#/definitions/Hostname"
            }
          ]
        },
        "port": {
          "description": "SMTP transport: Port to connect to. Default is 25 for plain, 465 for TLS and 587 for `StartTLS`",
          "type": "integer",
          "format": "uint16",
          "maximum": 65535.0,
          "minimum": 1.0
        },
        "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"
        },
        "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"
        },
        "command": {
          "description": "Sendmail transport: Command to use to send emails",
          "default": "sendmail",
          "type": "string"
        }
      }
    },
    "EmailTransportKind": {
      "description": "What backend should be used when sending emails",
      "oneOf": [
        {
          "description": "Don't send emails anywhere",
          "type": "string",
          "enum": [
            "blackhole"
          ]
        },
        {
          "description": "Send emails via an SMTP relay",
          "type": "string",
          "enum": [
            "smtp"
          ]
        },
        {
          "description": "Send emails by calling sendmail",
          "type": "string",
          "enum": [
            "sendmail"
          ]
        }
      ]
    },
    "EmailSmtpMode": {
      "description": "Encryption mode to use",
      "oneOf": [
        {
          "description": "Plain text",
          "type": "string",
          "enum": [
            "plain"
          ]
        },
        {
          "description": "`StartTLS` (starts as plain text then upgrade to TLS)",
          "type": "string",
          "enum": [
            "starttls"
          ]
        },
        {
          "description": "TLS",
          "type": "string",
          "enum": [
            "tls"
          ]
        }
      ]
    },
    "SecretsConfig": {
      "description": "Application secrets",
      "type": "object",
      "required": [
        "encryption"
      ],
      "properties": {
        "encryption": {
          "description": "Encryption key for secure cookies",
          "examples": [
            "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff"
          ],
          "type": "string",
          "pattern": "[0-9a-fA-F]{64}"
        },
        "keys": {
          "description": "List of private keys to use for signing and encrypting payloads",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/KeyConfig"
          }
        }
      }
    },
    "KeyConfig": {
      "type": "object",
      "required": [
        "kid"
      ],
      "properties": {
        "kid": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "password_file": {
          "type": "string"
        },
        "key": {
          "type": "string"
        },
        "key_file": {
          "type": "string"
        }
      }
    },
    "PasswordsConfig": {
      "description": "User password hashing config",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Whether password-based authentication is enabled",
          "default": true,
          "type": "boolean"
        },
        "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.",
          "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,
          "type": "integer",
          "format": "uint8",
          "minimum": 0.0
        }
      }
    },
    "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.",
          "type": "integer",
          "format": "uint16",
          "minimum": 0.0
        },
        "algorithm": {
          "description": "The hashing algorithm to use",
          "allOf": [
            {
              "$ref": "#/definitions/Algorithm"
            }
          ]
        },
        "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.",
          "type": "boolean"
        },
        "cost": {
          "description": "Cost for the bcrypt algorithm",
          "default": 12,
          "type": "integer",
          "format": "uint32",
          "minimum": 0.0
        },
        "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"
        },
        "secret_file": {
          "description": "Same as `secret`, but read from a file.",
          "type": "string"
        }
      }
    },
    "Algorithm": {
      "description": "A hashing algorithm",
      "oneOf": [
        {
          "description": "bcrypt",
          "type": "string",
          "enum": [
            "bcrypt"
          ]
        },
        {
          "description": "argon2id",
          "type": "string",
          "enum": [
            "argon2id"
          ]
        },
        {
          "description": "PBKDF2",
          "type": "string",
          "enum": [
            "pbkdf2"
          ]
        }
      ]
    },
    "MatrixConfig": {
      "description": "Configuration related to the Matrix homeserver",
      "type": "object",
      "required": [
        "secret"
      ],
      "properties": {
        "kind": {
          "description": "The kind of homeserver it is.",
          "default": "synapse",
          "allOf": [
            {
              "$ref": "#/definitions/HomeserverKind"
            }
          ]
        },
        "homeserver": {
          "description": "The server name of the homeserver.",
          "default": "localhost:8008",
          "type": "string"
        },
        "secret": {
          "description": "Shared secret to use for calls to the admin API",
          "type": "string"
        },
        "endpoint": {
          "description": "The base URL of the homeserver's client API",
          "default": "http://localhost:8008/",
          "type": "string",
          "format": "uri"
        }
      }
    },
    "HomeserverKind": {
      "description": "The kind of homeserver it is.",
      "oneOf": [
        {
          "description": "Homeserver is Synapse",
          "type": "string",
          "enum": [
            "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.",
          "type": "string",
          "enum": [
            "synapse_read_only"
          ]
        }
      ]
    },
    "PolicyConfig": {
      "description": "Application secrets",
      "type": "object",
      "properties": {
        "wasm_module": {
          "description": "Path to the WASM module",
          "type": "string"
        },
        "client_registration_entrypoint": {
          "description": "Entrypoint to use when evaluating client registrations",
          "type": "string"
        },
        "register_entrypoint": {
          "description": "Entrypoint to use when evaluating user registrations",
          "type": "string"
        },
        "authorization_grant_entrypoint": {
          "description": "Entrypoint to use when evaluating authorization grants",
          "type": "string"
        },
        "password_entrypoint": {
          "description": "Entrypoint to use when changing password",
          "type": "string"
        },
        "email_entrypoint": {
          "description": "Entrypoint to use when adding an email address",
          "type": "string"
        },
        "data": {
          "description": "Arbitrary data to pass to the policy"
        }
      }
    },
    "RateLimitingConfig": {
      "description": "Configuration related to sending emails",
      "type": "object",
      "properties": {
        "account_recovery": {
          "description": "Account Recovery-specific rate limits",
          "default": {
            "per_ip": {
              "burst": 3,
              "per_second": 0.0008333333333333334
            },
            "per_address": {
              "burst": 3,
              "per_second": 0.0002777777777777778
            }
          },
          "allOf": [
            {
              "$ref": "#/definitions/AccountRecoveryRateLimitingConfig"
            }
          ]
        },
        "login": {
          "description": "Login-specific rate limits",
          "default": {
            "per_ip": {
              "burst": 3,
              "per_second": 0.05
            },
            "per_account": {
              "burst": 1800,
              "per_second": 0.5
            }
          },
          "allOf": [
            {
              "$ref": "#/definitions/LoginRateLimitingConfig"
            }
          ]
        },
        "registration": {
          "description": "Controls how many registrations attempts are permitted based on source address.",
          "default": {
            "burst": 3,
            "per_second": 0.0008333333333333334
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        },
        "email_authentication": {
          "description": "Email authentication-specific rate limits",
          "default": {
            "per_ip": {
              "burst": 5,
              "per_second": 0.016666666666666666
            },
            "per_address": {
              "burst": 3,
              "per_second": 0.0002777777777777778
            },
            "emails_per_session": {
              "burst": 2,
              "per_second": 0.0033333333333333335
            },
            "attempt_per_session": {
              "burst": 10,
              "per_second": 0.016666666666666666
            }
          },
          "allOf": [
            {
              "$ref": "#/definitions/EmailauthenticationRateLimitingConfig"
            }
          ]
        }
      }
    },
    "AccountRecoveryRateLimitingConfig": {
      "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.",
          "default": {
            "burst": 3,
            "per_second": 0.0008333333333333334
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        },
        "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.",
          "default": {
            "burst": 3,
            "per_second": 0.0002777777777777778
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        }
      }
    },
    "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.",
          "type": "integer",
          "format": "uint32",
          "minimum": 1.0
        },
        "per_second": {
          "description": "How quickly the allowance replenishes, in number of actions per second. Can be fractional to replenish slower.",
          "type": "number",
          "format": "double"
        }
      }
    },
    "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.",
          "default": {
            "burst": 3,
            "per_second": 0.05
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        },
        "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.",
          "default": {
            "burst": 1800,
            "per_second": 0.5
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        }
      }
    },
    "EmailauthenticationRateLimitingConfig": {
      "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.",
          "default": {
            "burst": 5,
            "per_second": 0.016666666666666666
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        },
        "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.",
          "default": {
            "burst": 3,
            "per_second": 0.0002777777777777778
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        },
        "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.",
          "default": {
            "burst": 2,
            "per_second": 0.0033333333333333335
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        },
        "attempt_per_session": {
          "description": "Controls how many code authentication attempts are permitted per authentication session. This can protect against brute-forcing the code.",
          "default": {
            "burst": 10,
            "per_second": 0.016666666666666666
          },
          "allOf": [
            {
              "$ref": "#/definitions/RateLimiterConfiguration"
            }
          ]
        }
      }
    },
    "UpstreamOAuth2Config": {
      "description": "Upstream OAuth 2.0 providers configuration",
      "type": "object",
      "required": [
        "providers"
      ],
      "properties": {
        "providers": {
          "description": "List of OAuth 2.0 providers",
          "type": "array",
          "items": {
            "$ref": "#/definitions/Provider"
          }
        }
      }
    },
    "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`",
          "type": "boolean"
        },
        "id": {
          "description": "A ULID as per https://github.com/ulid/spec",
          "type": "string",
          "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"
        },
        "issuer": {
          "description": "The OIDC issuer URL\n\nThis is required if OIDC discovery is enabled (which is the default)",
          "type": "string"
        },
        "human_name": {
          "description": "A human-readable name for the provider, that will be shown to users",
          "type": "string"
        },
        "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"
        },
        "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"
        },
        "token_endpoint_auth_method": {
          "description": "The method to authenticate the client with the provider",
          "allOf": [
            {
              "$ref": "#/definitions/TokenAuthMethod"
            }
          ]
        },
        "sign_in_with_apple": {
          "description": "Additional parameters for the `sign_in_with_apple` method",
          "allOf": [
            {
              "$ref": "#/definitions/SignInWithApple"
            }
          ]
        },
        "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": [
            {
              "$ref": "#/definitions/JsonWebSignatureAlg"
            }
          ]
        },
        "id_token_signed_response_alg": {
          "description": "Expected signature for the JWT payload returned by the token authentication endpoint.\n\nDefaults to `RS256`.",
          "allOf": [
            {
              "$ref": "#/definitions/JsonWebSignatureAlg"
            }
          ]
        },
        "scope": {
          "description": "The scopes to request from the provider\n\nDefaults 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",
          "allOf": [
            {
              "$ref": "#/definitions/DiscoveryMode"
            }
          ]
        },
        "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.",
          "allOf": [
            {
              "$ref": "#/definitions/PkceMethod"
            }
          ]
        },
        "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"
        },
        "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": [
            {
              "$ref": "#/definitions/JsonWebSignatureAlg"
            }
          ]
        },
        "authorization_endpoint": {
          "description": "The URL to use for the provider's authorization endpoint\n\nDefaults to the `authorization_endpoint` provided through discovery",
          "type": "string",
          "format": "uri"
        },
        "userinfo_endpoint": {
          "description": "The URL to use for the provider's userinfo endpoint\n\nDefaults to the `userinfo_endpoint` provided through discovery",
          "type": "string",
          "format": "uri"
        },
        "token_endpoint": {
          "description": "The URL to use for the provider's token endpoint\n\nDefaults to the `token_endpoint` provided through discovery",
          "type": "string",
          "format": "uri"
        },
        "jwks_uri": {
          "description": "The URL to use for getting the provider's public keys\n\nDefaults to the `jwks_uri` provided through discovery",
          "type": "string",
          "format": "uri"
        },
        "response_mode": {
          "description": "The response mode we ask the provider to use for the callback",
          "allOf": [
            {
              "$ref": "#/definitions/ResponseMode"
            }
          ]
        },
        "claims_imports": {
          "description": "How claims should be imported from the `id_token` provided by the provider",
          "allOf": [
            {
              "$ref": "#/definitions/ClaimsImports"
            }
          ]
        },
        "additional_authorization_parameters": {
          "description": "Additional parameters to include in the authorization request\n\nOrders 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"
        }
      }
    },
    "TokenAuthMethod": {
      "description": "Authentication methods used against the OAuth 2.0 provider",
      "oneOf": [
        {
          "description": "`none`: No authentication",
          "type": "string",
          "enum": [
            "none"
          ]
        },
        {
          "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic authorization credentials",
          "type": "string",
          "enum": [
            "client_secret_basic"
          ]
        },
        {
          "description": "`client_secret_post`: `client_id` and `client_secret` sent in the request body",
          "type": "string",
          "enum": [
            "client_secret_post"
          ]
        },
        {
          "description": "`client_secret_jwt`: a `client_assertion` sent in the request body and signed using the `client_secret`",
          "type": "string",
          "enum": [
            "client_secret_jwt"
          ]
        },
        {
          "description": "`private_key_jwt`: a `client_assertion` sent in the request body and signed by an asymmetric key",
          "type": "string",
          "enum": [
            "private_key_jwt"
          ]
        },
        {
          "description": "`sign_in_with_apple`: a special method for Signin with Apple",
          "type": "string",
          "enum": [
            "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"
        },
        "private_key": {
          "description": "The private key used to sign the `id_token`",
          "type": "string"
        },
        "team_id": {
          "description": "The Team ID of the Apple Developer Portal",
          "type": "string"
        },
        "key_id": {
          "description": "The key ID of the Apple Developer Portal",
          "type": "string"
        }
      }
    },
    "DiscoveryMode": {
      "description": "How to discover the provider's configuration",
      "oneOf": [
        {
          "description": "Use OIDC discovery with strict metadata verification",
          "type": "string",
          "enum": [
            "oidc"
          ]
        },
        {
          "description": "Use OIDC discovery with relaxed metadata verification",
          "type": "string",
          "enum": [
            "insecure"
          ]
        },
        {
          "description": "Use a static configuration",
          "type": "string",
          "enum": [
            "disabled"
          ]
        }
      ]
    },
    "PkceMethod": {
      "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.",
      "oneOf": [
        {
          "description": "Use PKCE if the provider supports it\n\nDefaults to no PKCE if provider discovery is disabled",
          "type": "string",
          "enum": [
            "auto"
          ]
        },
        {
          "description": "Always use PKCE with the S256 challenge method",
          "type": "string",
          "enum": [
            "always"
          ]
        },
        {
          "description": "Never use PKCE",
          "type": "string",
          "enum": [
            "never"
          ]
        }
      ]
    },
    "ResponseMode": {
      "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",
          "type": "string",
          "enum": [
            "query"
          ]
        },
        {
          "description": "`form_post`: The provider will send the response as a POST request with the response parameters in the request body\n\n<https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html>",
          "type": "string",
          "enum": [
            "form_post"
          ]
        }
      ]
    },
    "ClaimsImports": {
      "description": "How claims should be imported",
      "type": "object",
      "properties": {
        "subject": {
          "description": "How to determine the subject of the user",
          "allOf": [
            {
              "$ref": "#/definitions/SubjectImportPreference"
            }
          ]
        },
        "localpart": {
          "description": "Import the localpart of the MXID",
          "allOf": [
            {
              "$ref": "#/definitions/LocalpartImportPreference"
            }
          ]
        },
        "displayname": {
          "description": "Import the displayname of the user.",
          "allOf": [
            {
              "$ref": "#/definitions/DisplaynameImportPreference"
            }
          ]
        },
        "email": {
          "description": "Import the email address of the user based on the `email` and `email_verified` claims",
          "allOf": [
            {
              "$ref": "#/definitions/EmailImportPreference"
            }
          ]
        },
        "account_name": {
          "description": "Set a human-readable name for the upstream account for display purposes",
          "allOf": [
            {
              "$ref": "#/definitions/AccountNameImportPreference"
            }
          ]
        }
      }
    },
    "SubjectImportPreference": {
      "description": "What should be done for the subject attribute",
      "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"
        }
      }
    },
    "LocalpartImportPreference": {
      "description": "What should be done for the localpart attribute",
      "type": "object",
      "properties": {
        "action": {
          "description": "How to handle the attribute",
          "allOf": [
            {
              "$ref": "#/definitions/ImportAction"
            }
          ]
        },
        "template": {
          "description": "The Jinja2 template to use for the localpart attribute\n\nIf not provided, the default template is `{{ user.preferred_username }}`",
          "type": "string"
        }
      }
    },
    "ImportAction": {
      "description": "How to handle a claim",
      "oneOf": [
        {
          "description": "Ignore the claim",
          "type": "string",
          "enum": [
            "ignore"
          ]
        },
        {
          "description": "Suggest the claim value, but allow the user to change it",
          "type": "string",
          "enum": [
            "suggest"
          ]
        },
        {
          "description": "Force the claim value, but don't fail if it is missing",
          "type": "string",
          "enum": [
            "force"
          ]
        },
        {
          "description": "Force the claim value, and fail if it is missing",
          "type": "string",
          "enum": [
            "require"
          ]
        }
      ]
    },
    "DisplaynameImportPreference": {
      "description": "What should be done for the displayname attribute",
      "type": "object",
      "properties": {
        "action": {
          "description": "How to handle the attribute",
          "allOf": [
            {
              "$ref": "#/definitions/ImportAction"
            }
          ]
        },
        "template": {
          "description": "The Jinja2 template to use for the displayname attribute\n\nIf not provided, the default template is `{{ user.name }}`",
          "type": "string"
        }
      }
    },
    "EmailImportPreference": {
      "description": "What should be done with the email attribute",
      "type": "object",
      "properties": {
        "action": {
          "description": "How to handle the claim",
          "allOf": [
            {
              "$ref": "#/definitions/ImportAction"
            }
          ]
        },
        "template": {
          "description": "The Jinja2 template to use for the email address attribute\n\nIf not provided, the default template is `{{ user.email }}`",
          "type": "string"
        }
      }
    },
    "AccountNameImportPreference": {
      "description": "What should be done for the account name attribute",
      "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"
        }
      }
    },
    "BrandingConfig": {
      "description": "Configuration section for tweaking the branding of the service",
      "type": "object",
      "properties": {
        "service_name": {
          "description": "A human-readable name. Defaults to the server's address.",
          "type": "string"
        },
        "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.",
          "type": "string",
          "format": "uri"
        },
        "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.",
          "type": "string",
          "format": "uri"
        },
        "imprint": {
          "description": "Legal imprint, displayed in the footer in the footer of web pages and emails.",
          "type": "string"
        },
        "logo_uri": {
          "description": "Logo displayed in some web pages.",
          "type": "string",
          "format": "uri"
        }
      }
    },
    "CaptchaConfig": {
      "description": "Configuration section to setup CAPTCHA protection on a few operations",
      "type": "object",
      "properties": {
        "service": {
          "description": "Which service should be used for CAPTCHA protection",
          "allOf": [
            {
              "$ref": "#/definitions/CaptchaServiceKind"
            }
          ]
        },
        "site_key": {
          "description": "The site key to use",
          "type": "string"
        },
        "secret_key": {
          "description": "The secret key to use",
          "type": "string"
        }
      }
    },
    "CaptchaServiceKind": {
      "description": "Which service should be used for CAPTCHA protection",
      "oneOf": [
        {
          "description": "Use Google's reCAPTCHA v2 API",
          "type": "string",
          "enum": [
            "recaptcha_v2"
          ]
        },
        {
          "description": "Use Cloudflare Turnstile",
          "type": "string",
          "enum": [
            "cloudflare_turnstile"
          ]
        },
        {
          "description": "Use ``HCaptcha``",
          "type": "string",
          "enum": [
            "hcaptcha"
          ]
        }
      ]
    },
    "AccountConfig": {
      "description": "Configuration section to configure features related to account management",
      "type": "object",
      "properties": {
        "email_change_allowed": {
          "description": "Whether users are allowed to change their email addresses. Defaults to `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.",
          "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.",
          "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.",
          "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.",
          "type": "boolean"
        },
        "account_deactivation_allowed": {
          "description": "Whether users are allowed to delete their own account. Defaults to `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.",
          "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.",
          "type": "boolean"
        }
      }
    },
    "ExperimentalConfig": {
      "description": "Configuration sections for experimental options\n\nDo 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
        },
        "compat_token_ttl": {
          "description": "Time-to-live of compatibility access tokens in seconds. Defaults to 5 minutes.",
          "type": "integer",
          "format": "uint64",
          "maximum": 86400.0,
          "minimum": 60.0
        },
        "inactive_session_expiration": {
          "description": "Experimetal feature to automatically expire inactive sessions\n\nDisabled by default",
          "allOf": [
            {
              "$ref": "#/definitions/InactiveSessionExpirationConfig"
            }
          ]
        }
      }
    },
    "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
        },
        "expire_compat_sessions": {
          "description": "Should compatibility sessions expire after inactivity",
          "default": true,
          "type": "boolean"
        },
        "expire_oauth_sessions": {
          "description": "Should OAuth 2.0 sessions expire after inactivity",
          "default": true,
          "type": "boolean"
        },
        "expire_user_sessions": {
          "description": "Should user sessions expire after inactivity",
          "default": true,
          "type": "boolean"
        }
      }
    }
  }
}