{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://www.nucleus-cms.com/schemas/config.schema.json",
  "title": "Nucleus Configuration",
  "description": "Nucleus options configuration",
  "version": "4.0.0",
  "type": "object",
  "allOf": [
    { "$ref": "https://json.schemastore.org/appsettings.json" }
  ],
  "properties": {
    "Nucleus": {
      "type": "object",
      "properties": {
        "MachineName": {
          "type": "string",
          "description": "Specifies the name used to identify the server in logging filenames, for scheduled task history and in observability/instrumentation. If not set, the value is set to the result of Environment.MachineName, which is the NETBIOS name of the computer in Windows, or the value of the HOSTNAME environment variable in Linux. Using this value to override the machine name is useful in some hosted environments, where the name of the underlying virtual machine may change."
        },
        "MaxRequestSize": {
          "type": "integer",
          "description": "Specifies the maximum [MultipartBodyLengthLimit](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.features.formoptions.multipartbodylengthlimit) and [MaxRequestBodySize](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserverlimits.maxrequestbodysize) in bytes.  This value must be set high enough for the largest file upload that you want to allow.  If not specified, the .net core defaults are used."
        },
        "ForwardedHeaders": {
          "type": "object",
          "properties": {
            "Enabled": { "type": "boolean" },
            "KnownNetworks": {
              "type": "array",
              "description": "Specifies A list of reverse proxy networks which are trusted to send forwarded headers.  Each KnownNetwork entry contains a prefix and a prefix length. The prefix is in IP address format, and the prefix length is a subnet, in CIDR notation.",
              "items": {
                "type": "object",
                "properties": {
                  "prefix": {
                    "type": "string",
                    "description": "The prefix is in IP address format."
                  },
                  "prefixlength": {
                    "type": "integer",
                    "description": "Subnet length, in CIDR notation.",
                    "minimum": 0,
                    "maximum": 32
                  }
                },
                "required": [ "prefix", "prefixlength" ],
                "additionalProperties": true
              }
            },
            "KnownProxies": {
              "type": "array",
              "description": "Specifies A list of reverse proxy servers which are trusted to send forwarded headers.",
              "items": { "type": "string" }
            }
          },
          "additionalProperties": true
        },
        "InstrumentationOptions": {
          "type": "object",
          "properties": {
            "Meters": {
              "type": "object",
              "properties": {
                "Enabled": { "type": "boolean" },
                "OtlpEndPoint": { "type": "string" }
              },
              "additionalProperties": true
            }
          },
          "additionalProperties": true
        },
        "HealthChecks": {
          "type": "object",
          "properties": {
            "Enabled": { "type": "boolean" },
            "HealthCheckEndPoint": {
              "type": "string",
              "description": "The local path of the health check endpoint.",
              "default": "/_health"
            },
            "LiveCheckEndPoint": {
              "type": "string",
              "description": "The local path of the live check endpoint.",
              "default": "/_live"
            },
            "ReadyCheckEndPoint": {
              "type": "string",
              "description": "The local path of the ready check endpoint.",
              "default": "/_ready"
            },
            "RequireRoles": {
              "type": "string",
              "description": "A comma-separated list of roles that are allowed to access the health check endpoints. If set, the caller must use an Api Key and sign the request, or access the endpoint from a web browser after logging in to Nucleus. The default value is not set, which allows anonymous access."
            }
          },
          "additionalProperties": true
        },
        "FolderOptions": {
          "type": "object",
          "properties": {
            "DataFolder": {
              "type": "string",
              "description": "Specifies the name of the root folder that Nucleus uses to store files on the file system. The DataFolder setting can contain environment variables like `%ProgramData%`, which are resolved at run time."
            }
          },
          "additionalProperties": true
        },
        "TextFileLoggerOptions": {
          "type": "object",
          "properties": {
            "Path": {
              "type": "string",
              "description": "Specifies the name of the folder that the Nucleus text file logger uses to store log files on the file system. By default, this value is the `Logs` subfolder of the folder specified by `Nucleus:FolderOptions:DataFolder`."
            },
            "LogFileExpiry": {
              "type": "string",
              "description": "Specifies how long log files are retained before being automatically deleted.  This value is a TimeSpan, which is represented in days, hours, minutes and seconds in the form `days:hours:minutes:seconds`.  For example, 7 days, 11 hours, 20 minutes and 15 seconds would be represented as `07:11:20:15`.  The default value is 7 days (`07:00:00:00`).",
              "default": "07:00:00:00"
            }
          },
          "additionalProperties": true
        },
        "ResourceFileOptions": {
          "type": "object",
          "properties": {
            "UseMinifiedJs": {
              "type": "boolean",
              "description": "Specifies whether to use minified JavaScript files, when they are available.",
              "default": true
            },
            "UseMinifiedCss": {
              "type": "boolean",
              "description": "Specifies whether to use minified CSS files, when they are available.",
              "default": true
            }
          },
          "additionalProperties": true
        },
        "EnableResponseCompression": { "type": [ "boolean", "string" ] },
        "EnableForwardedHeaders": { "type": [ "boolean", "string" ] },

        "FileSystems": {
          "type": "object",
          "properties": {
            "AllowedFileTypes": {
              "type": "array",
              "description": "AllowedFileTypes are used to specify one or more file extensions and a list of signatures for each file type. Uploaded files must match a specified file extension, and one of the signatures must match, if any are specified.",
              "items": {
                "type": "object",
                "properties": {
                  "FileExtensions": {
                    "type": "array",
                    "description": "A list of file extensions, including the leading period. For example, `.jpg`.",
                    "items": { "type": "string" }
                  },
                  "Signatures": {
                    "type": "array",
                    "description": "A list of file signatures for the file type. Each signature is a string of hexadecimal characters representing the bytes at the beginning of the file. The special value `??` in a signature skips validation of the byte in the ordinal position represented by the ?? characters. Up to 64 bytes can be specified.",
                    "items": { "type": "string" }
                  },
                  "Restricted": {
                    "type": "boolean",
                    "description": "If true, upload of files of this type is limited to system and site administrators.",
                    "default": false
                  }
                }
              }
            },
            "Providers": {
              "type": "array",
              "description": "File system providers have a key, name and provider type. Many cloud file system providers also have a ConnectionString.",
              "items": {
                "type": "object",
                "properties": {
                  "Key": {
                    "type": "string",
                    "description": "The key is used to identify the file system provider in configuration and database entries. The Key should not be changed after you have started using Nucleus."
                  },
                  "Name": {
                    "type": "string",
                    "description": "The name is a human-readable name for the file system provider, used for on-screen display."
                  },
                  "ProviderType": {
                    "type": "string",
                    "description": "The provider type is the fully-qualified name of the class that implements the IFileSystemProvider interface.",
                    "anyOf": [
                      {
                        "enum": [
                          "Nucleus.Core.FileSystemProviders.LocalFileSystemProvider,Nucleus.Core",
                          "Nucleus.Extensions.AzureBlobStorageFileSystemProvider.FileSystemProvider,Nucleus.Extensions.AzureBlobStorageFileSystemProvider",
                          "Nucleus.Extensions.AmazonS3FileSystemProvider.FileSystemProvider,Nucleus.Extensions.AmazonS3FileSystemProvider",
                          "Nucleus.Extensions.SharePointFileSystemProvider.FileSystemProvider,Nucleus.Extensions.SharePointFileSystemProvider",
                          "Nucleus.Extensions.GoogleStorageCloudFileSystemProvider.FileSystemProvider,Nucleus.Extensions.GoogleStorageCloudFileSystemProvider"
                        ]
                      },
                      { "type": "string" }
                    ]
                  },
                  "ConnectionString": {
                    "type": "string",
                    "description": "The connection string is used to connect to the file system provider. The format of the connection string depends on the provider type."
                  }
                },
                "additionalProperties": true
              }              
            }
          }
        },

        "AuthenticationSchemeOptions": {
          "type": "object",
          "properties": {
            "ExpiryTimeSpan": {
              "type": "string",
              "description": "Login session expiry (time span)."
            },
            "LongExpiryTimeSpan": {
              "type": "string",
              "description": "Login session expiry (time span) when the `remember me` option is selected."
            },
            "SlidingExpirationTimeSpan": {
              "type": "string",
              "description": "TimeSpan string"
            },
            "EnforceSameIPAddress": {
              "type": "boolean",
              "description": "Specifies whether to enforce the same IP address for the entire session. If a request from another IP address is received, the session will be invalidated. This can cause problems in environments where users have dynamic IP addresses or have multiple network interfaces."
            }
          },
          "additionalProperties": true
        },
        "PasswordOptions": {
          "type": "object",
          "properties": {
            "FailedPasswordWindowTimeout": {
              "type": "string",
              "description": "Specifies the time span for which the system remembers that a user has had a failed password attempt.  Repeated failures within the specified file will increment the failed password attempts count, and when the FailedPasswordMaxAttempts threshold is exceeded, the user account will be locked for a period of time.  Default value is 0:15:00 (15 minutes)."
            },
            "FailedPasswordMaxAttempts": {
              "type": "integer",
              "description": "Specifies the number of failed password attempts before account lockout.  Default value is 3. | ",
              "minimum": 0
            },
            "FailedPasswordLockoutReset": {
              "type": "string",
              "description": "Specifies the time span after which an account lockout is automatically reset.  Default value is 0:10:00 (10 minutes)."
            },
            "PasswordResetTokenExpiry": {
              "type": "string",
              "description": "Specifies the time span after which a password reset token expires.  Password reset tokens are sent to the user when they request a password reset.  Default value is 02:00:00 (2 hours)."
            },
            "PasswordComplexityRules": {
              "type": "array",
              "description": "A list of rules that define the complexity requirements for passwords. You can specify multiple password complexity rules and all of them must succeed (match) in order for a password to be valid.",
              "items": {
                "type": "object",
                "properties": {
                  "Pattern": {
                    "type": "string",
                    "description": "A regular expression pattern for the password complexity rule."
                  },
                  "Message": {
                    "type": "string",
                    "description": "The error message to display if the password does not meet the complexity rule."
                  }
                },
                "required": [ "Pattern", "Message" ]
              }
            }
          },
          "additionalProperties": true
        },
        "CacheOptions": {
          "type": "object",
          "additionalProperties": {
            "type": "object",
            "properties": {
              "Capacity": {
                "type": "integer",
                "description": "Number of entities to cache in memory.",
                "default": 1000
              },
              "ExpiryTime": {
                "type": "string",
                "description": "Expiry time for cache entries (time span).",
                "default": "00:15:00"
              }
            }            
          }
        },
        "SecurityHeaderOptions": {
          "type": "object",
          "properties": {
            "Headers": {
              "type": "string",
              "description": "Specifies the value of the X-Frame-Options header.  This header is used to prevent clickjacking attacks.  Valid values are DENY, SAMEORIGIN, or ALLOW-FROM uri.  Default value is SAMEORIGIN."
            },
            "Directives": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "Name": {
                    "type": "string",
                    "description": "The name of the Content Security Policy directive."
                  },
                  "Value": {
                    "type": "string",
                    "description": "The value of the Content Security Policy directive. If you want to add extra Uris to the directive, use the Uris property instead."
                  },
                  "Uris": {
                    "type": "string",
                    "description": "A list of space-separated URIs that are used for this directive. Depending on the value of the UriOperation property, the URIs are either added to the automatically-derived URIs, or appended."
                  },
                  "UriOperation": {
                    "type": "string",
                    "description": "Specifies how the URIs specified in the Uris property are used. Valid values are Append or Replace. If Append, the URIs specified in the Uris property are appended to the automatically-derived URIs for this directive. If Replace, the URIs specified in the Uris property replace the automatically-derived URIs for this directive.",
                    "enum": [ "Append", "Replace" ],
                    "default": "Append"
                  }
                }
              },
              "ReportUri": {
                "type": "string",
                "description": "If set, overrides the URI to which Content Security Policy violation reports should be sent. If this setting is specified and set to an empty string, disables CSP reporting.",
                "default": "/_csp-reports"
              },
              "ReportOnly": {
                "type": "boolean",
                "description": "If true, enables Content Security Policy report-only mode."
              }
            }
          }
        },
        "additionalProperties": true
      }
    },
    "additionalProperties": true
  }
}