# Security Schema - Security configurations (TLS, secrets, auth)
# Version: 1.0.0

{
  # TLS/SSL configuration
  TlsConfig = {
    enabled
      | Bool
      | doc "Enable TLS/SSL"
      | default = false,

    cert_path
      | String
      | doc "Path to TLS certificate file"
      | {
        label = "valid path",
        predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256
      }
      | optional,

    key_path
      | String
      | doc "Path to TLS private key file"
      | {
        label = "valid path",
        predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256
      }
      | optional,

    ca_path
      | String
      | doc "Path to CA certificate file"
      | {
        label = "valid path",
        predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256
      }
      | optional,

    min_version
      | [| 'TLSv1.0, 'TLSv1.1, 'TLSv1.2, 'TLSv1.3 |]
      | doc "Minimum TLS version"
      | default = 'TLSv1.2,

    max_version
      | [| 'TLSv1.2, 'TLSv1.3 |]
      | doc "Maximum TLS version"
      | default = 'TLSv1.3,

    cipher_suites
      | Array String
      | doc "Allowed cipher suites"
      | default = [],

    verify_client
      | Bool
      | doc "Require client certificate verification"
      | default = false,

    auto_generate
      | Bool
      | doc "Auto-generate self-signed certificates for development"
      | default = false,
  },

  # Secret definition
  SecretDefinition = {
    name
      | String
      | doc "Secret name"
      | {
        label = "valid secret name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    type
      | [| 'Opaque, 'kubernetes.io/tls, 'kubernetes.io/dockerconfigjson, 'kubernetes.io/basic-auth, 'kubernetes.io/ssh-auth |]
      | doc "Secret type"
      | default = 'Opaque,

    data
      | {_: String}
      | doc "Secret data (key-value pairs, values will be base64 encoded)"
      | default = {},

    string_data
      | {_: String}
      | doc "Secret data as plain strings (will be auto-encoded)"
      | default = {},

    external
      | Bool
      | doc "Reference to external secret (managed outside provisioning)"
      | default = false,

    labels
      | {_: String}
      | doc "Secret labels"
      | default = {},
  },

  # Docker secret configuration
  DockerSecret = {
    name
      | String
      | doc "Secret name"
      | {
        label = "valid secret name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    file
      | String
      | doc "Path to secret file"
      | optional,

    external
      | Bool
      | doc "Reference to external secret"
      | default = false,

    labels
      | {_: String}
      | doc "Secret labels"
      | default = {},
  },

  # Authentication configuration
  AuthConfig = {
    method
      | [| 'none, 'basic, 'bearer, 'oauth2, 'jwt, 'api_key |]
      | doc "Authentication method"
      | default = 'none,

    basic
      | {
        username
          | String
          | doc "Basic auth username",

        password
          | String
          | doc "Basic auth password"
          | {
            label = "valid password",
            predicate = fun s => std.string.length s >= 8 && std.string.length s <= 128
          },

        realm
          | String
          | doc "Authentication realm"
          | default = "Restricted",
      }
      | doc "Basic authentication configuration"
      | optional,

    bearer
      | {
        token
          | String
          | doc "Bearer token",

        token_type
          | String
          | doc "Token type (e.g., 'Bearer')"
          | default = "Bearer",
      }
      | doc "Bearer token authentication configuration"
      | optional,

    oauth2
      | {
        provider
          | [| 'google, 'github, 'gitlab, 'azure, 'okta, 'custom |]
          | doc "OAuth2 provider",

        client_id
          | String
          | doc "OAuth2 client ID",

        client_secret
          | String
          | doc "OAuth2 client secret",

        auth_url
          | String
          | doc "Authorization URL"
          | optional,

        token_url
          | String
          | doc "Token URL"
          | optional,

        redirect_uri
          | String
          | doc "Redirect URI after authentication",

        scopes
          | Array String
          | doc "OAuth2 scopes to request"
          | default = [],
      }
      | doc "OAuth2 authentication configuration"
      | optional,

    jwt
      | {
        secret
          | String
          | doc "JWT signing secret",

        algorithm
          | [| 'HS256, 'HS384, 'HS512, 'RS256, 'RS384, 'RS512, 'ES256, 'ES384, 'ES512 |]
          | doc "JWT signing algorithm"
          | default = 'HS256,

        issuer
          | String
          | doc "JWT issuer"
          | optional,

        audience
          | Array String
          | doc "JWT audience"
          | default = [],

        expiry_seconds
          | Number
          | doc "Token expiry in seconds (300-86400)"
          | {
            label = "valid expiry",
            predicate = fun n => n >= 300 && n <= 86400
          }
          | default = 3600,

        public_key_path
          | String
          | doc "Path to public key for RS/ES algorithms"
          | optional,

        private_key_path
          | String
          | doc "Path to private key for RS/ES algorithms"
          | optional,
      }
      | doc "JWT authentication configuration"
      | optional,

    api_key
      | {
        header_name
          | String
          | doc "HTTP header name for API key"
          | default = "X-API-Key",

        query_param
          | String
          | doc "Query parameter name for API key"
          | optional,

        keys
          | Array {
            key
              | String
              | doc "API key value",

            name
              | String
              | doc "Key name/identifier"
              | optional,

            permissions
              | Array String
              | doc "Permissions granted to this key"
              | default = [],
          }
          | doc "List of valid API keys"
          | default = [],
      }
      | doc "API key authentication configuration"
      | optional,
  },

  # RBAC (Role-Based Access Control) configuration
  RbacRole = {
    name
      | String
      | doc "Role name",

    permissions
      | Array String
      | doc "List of permissions (e.g., ['read:users', 'write:posts'])"
      | default = [],

    resources
      | Array String
      | doc "Resources this role can access"
      | default = [],

    actions
      | Array ([| 'create, 'read, 'update, 'delete, 'list |])
      | doc "Allowed actions"
      | default = [],
  },

  RbacPolicy = {
    roles
      | Array RbacRole
      | doc "Role definitions"
      | default = [],

    default_role
      | String
      | doc "Default role for authenticated users"
      | default = "user",

    admin_role
      | String
      | doc "Administrator role name"
      | default = "admin",
  },

  # Security headers configuration
  SecurityHeaders = {
    enable_hsts
      | Bool
      | doc "Enable HTTP Strict Transport Security"
      | default = true,

    hsts_max_age
      | Number
      | doc "HSTS max age in seconds"
      | default = 31536000,

    hsts_include_subdomains
      | Bool
      | doc "Include subdomains in HSTS"
      | default = true,

    enable_csp
      | Bool
      | doc "Enable Content Security Policy"
      | default = true,

    csp_policy
      | String
      | doc "Content Security Policy directives"
      | default = "default-src 'self'",

    enable_xss_protection
      | Bool
      | doc "Enable X-XSS-Protection header"
      | default = true,

    enable_frame_options
      | Bool
      | doc "Enable X-Frame-Options header"
      | default = true,

    frame_options_value
      | [| 'DENY, 'SAMEORIGIN |]
      | doc "X-Frame-Options value"
      | default = 'DENY,

    enable_content_type_nosniff
      | Bool
      | doc "Enable X-Content-Type-Options: nosniff"
      | default = true,

    enable_referrer_policy
      | Bool
      | doc "Enable Referrer-Policy header"
      | default = true,

    referrer_policy_value
      | [| 'no-referrer, 'no-referrer-when-downgrade, 'same-origin, 'origin, 'strict-origin, 'origin-when-cross-origin, 'strict-origin-when-cross-origin, 'unsafe-url |]
      | doc "Referrer-Policy value"
      | default = 'strict-origin-when-cross-origin,

    custom_headers
      | {_: String}
      | doc "Additional custom security headers"
      | default = {},
  },

  # Main security configuration
  SecurityConfig = {
    tls
      | TlsConfig
      | doc "TLS/SSL configuration"
      | default = {enabled = false},

    docker_secrets
      | Array DockerSecret
      | doc "Docker secrets"
      | default = [],

    kubernetes_secrets
      | Array SecretDefinition
      | doc "Kubernetes secrets"
      | default = [],

    auth
      | AuthConfig
      | doc "Authentication configuration"
      | default = {method = 'none},

    rbac
      | RbacPolicy
      | doc "Role-Based Access Control configuration"
      | optional,

    security_headers
      | SecurityHeaders
      | doc "Security headers configuration"
      | default = {},

    cors
      | {
        enabled
          | Bool
          | doc "Enable CORS"
          | default = false,

        allowed_origins
          | Array String
          | doc "Allowed origins for CORS"
          | default = ["*"],

        allowed_methods
          | Array String
          | doc "Allowed HTTP methods"
          | default = ["GET", "POST", "PUT", "DELETE", "OPTIONS"],

        allowed_headers
          | Array String
          | doc "Allowed headers"
          | default = ["*"],

        expose_headers
          | Array String
          | doc "Headers to expose to the client"
          | default = [],

        allow_credentials
          | Bool
          | doc "Allow credentials in CORS requests"
          | default = false,

        max_age
          | Number
          | doc "Preflight cache duration in seconds"
          | default = 86400,
      }
      | doc "CORS configuration"
      | optional,

    rate_limiting
      | {
        enabled
          | Bool
          | doc "Enable rate limiting"
          | default = false,

        requests_per_second
          | Number
          | doc "Maximum requests per second"
          | default = 100,

        burst_size
          | Number
          | doc "Burst size for rate limiter"
          | default = 200,

        strategy
          | [| 'ip, 'user, 'api_key |]
          | doc "Rate limiting strategy"
          | default = 'ip,
      }
      | doc "Rate limiting configuration"
      | optional,
  },
}
