{
  "type": "featherpanel.settings.category",
  "id": "security",
  "name": "Security",
  "description": "Security and authentication settings",
  "icon": "shield",
  "setting_keys": [
    "email_login_enabled",
    "captcha_provider",
    "turnstile_enabled",
    "turnstile_key_pub",
    "turnstile_key_priv",
    "hcaptcha_site_key",
    "hcaptcha_secret_key",
    "recaptcha_site_key",
    "recaptcha_secret_key",
    "recaptcha_version",
    "recaptcha_v3_min_score",
    "recaptcha_v3_action",
    "friendly_captcha_site_key",
    "friendly_captcha_secret_key",
    "reforge_captcha_site_key",
    "reforge_captcha_secret_key",
    "reforge_captcha_widget_type",
    "reforge_captcha_theme",
    "reforge_captcha_size",
    "reforge_captcha_lang",
    "reforge_captcha_min_score",
    "registration_enabled",
    "registration_require_email_verification",
    "registration_device_limit_enabled",
    "registration_device_max_accounts",
    "email_domain_blocking_enabled",
    "abuseipdb_enabled",
    "abuseipdb_api_key",
    "abuseipdb_check_on_register",
    "abuseipdb_min_confidence_score",
    "abuseipdb_max_age_days",
    "abuseipdb_register_action",
    "require_two_fa_admins",
    "avatar_provider",
    "avatar_custom_url",
    "user_allow_avatar_change",
    "user_allow_username_change",
    "user_allow_email_change",
    "user_allow_first_name_change",
    "user_allow_last_name_change",
    "user_allow_api_keys_create",
    "user_allow_account_deletion",
    "user_account_deletion_mode",
    "user_account_deletion_delay_days",
    "user_account_deletion_verify_2fa",
    "user_account_deletion_verify_email_otp"
  ],
  "settings_count": 46,
  "settings": [
    {
      "key": "email_login_enabled",
      "constant": "EMAIL_LOGIN_ENABLED",
      "description": "Enable passwordless email login with 6-digit OTP codes sent to user email addresses (requires SMTP to be configured)",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "captcha_provider",
      "constant": "CAPTCHA_PROVIDER",
      "description": "Captcha service provider (Turnstile, hCaptcha, Google reCAPTCHA, Friendly Captcha, or reForge Captcha)",
      "type": "select",
      "required": true,
      "placeholder": "turnstile",
      "validation": "required|string|max:255",
      "options": [
        "turnstile",
        "hcaptcha",
        "recaptcha",
        "friendlycaptcha",
        "reforge"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "turnstile_enabled",
      "constant": "TURNSTILE_ENABLED",
      "description": "The Turnstile enabled of the application",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "turnstile_key_pub",
      "constant": "TURNSTILE_KEY_PUB",
      "description": "The Turnstile key pub of the application",
      "type": "text",
      "required": false,
      "placeholder": "",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "turnstile_key_priv",
      "constant": "TURNSTILE_KEY_PRIV",
      "description": "The Turnstile private key of the application",
      "type": "password",
      "required": false,
      "placeholder": "Enter private key to change",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": true
    },
    {
      "key": "hcaptcha_site_key",
      "constant": "HCAPTCHA_SITE_KEY",
      "description": "The hCaptcha site key of the application",
      "type": "text",
      "required": false,
      "placeholder": "",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "hcaptcha_secret_key",
      "constant": "HCAPTCHA_SECRET_KEY",
      "description": "The hCaptcha secret key of the application",
      "type": "password",
      "required": false,
      "placeholder": "Enter secret key to change",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": true
    },
    {
      "key": "recaptcha_site_key",
      "constant": "RECAPTCHA_SITE_KEY",
      "description": "The reCAPTCHA site key of the application",
      "type": "text",
      "required": false,
      "placeholder": "",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "recaptcha_secret_key",
      "constant": "RECAPTCHA_SECRET_KEY",
      "description": "The reCAPTCHA secret key of the application",
      "type": "password",
      "required": false,
      "placeholder": "Enter secret key to change",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": true
    },
    {
      "key": "recaptcha_version",
      "constant": "RECAPTCHA_VERSION",
      "description": "Use reCAPTCHA v2 (checkbox) or v3 (invisible score). Keys must match the version in Google Admin.",
      "type": "select",
      "required": true,
      "placeholder": "v2",
      "validation": "required|string|max:10",
      "options": [
        "v2",
        "v3"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "recaptcha_v3_min_score",
      "constant": "RECAPTCHA_V3_MIN_SCORE",
      "description": "Minimum v3 score (0.0–1.0). Higher is stricter. Ignored when version is v2.",
      "type": "text",
      "required": true,
      "placeholder": "0.5",
      "validation": "required|string|max:10",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "recaptcha_v3_action",
      "constant": "RECAPTCHA_V3_ACTION",
      "description": "reCAPTCHA v3 action name (must match what the frontend sends). Use letters, numbers, underscores, and slashes only.",
      "type": "text",
      "required": true,
      "placeholder": "submit",
      "validation": "required|string|max:100",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "friendly_captcha_site_key",
      "constant": "FRIENDLY_CAPTCHA_SITE_KEY",
      "description": "The Friendly Captcha site key of the application",
      "type": "text",
      "required": false,
      "placeholder": "",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "friendly_captcha_secret_key",
      "constant": "FRIENDLY_CAPTCHA_SECRET_KEY",
      "description": "The Friendly Captcha secret key of the application",
      "type": "password",
      "required": false,
      "placeholder": "Enter secret key to change",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": true
    },
    {
      "key": "reforge_captcha_site_key",
      "constant": "REFORGE_CAPTCHA_SITE_KEY",
      "description": "reForge Captcha public site key (from dashboard → Sites)",
      "type": "text",
      "required": false,
      "placeholder": "site_...",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "reforge_captcha_secret_key",
      "constant": "REFORGE_CAPTCHA_SECRET_KEY",
      "description": "reForge Captcha secret key (server-side only; never expose to the browser)",
      "type": "password",
      "required": false,
      "placeholder": "Enter secret key to change",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": true
    },
    {
      "key": "reforge_captcha_widget_type",
      "constant": "REFORGE_CAPTCHA_WIDGET_TYPE",
      "description": "reForge Captcha widget challenge type (checkbox or image)",
      "type": "select",
      "required": true,
      "placeholder": "checkbox",
      "validation": "required|string|max:32",
      "options": [
        "checkbox",
        "image"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "reforge_captcha_theme",
      "constant": "REFORGE_CAPTCHA_THEME",
      "description": "reForge Captcha widget colour theme",
      "type": "select",
      "required": true,
      "placeholder": "auto",
      "validation": "required|string|max:16",
      "options": [
        "auto",
        "dark",
        "light"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "reforge_captcha_size",
      "constant": "REFORGE_CAPTCHA_SIZE",
      "description": "reForge Captcha widget size",
      "type": "select",
      "required": true,
      "placeholder": "normal",
      "validation": "required|string|max:16",
      "options": [
        "normal",
        "compact"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "reforge_captcha_lang",
      "constant": "REFORGE_CAPTCHA_LANG",
      "description": "Optional reForge Captcha widget UI language (e.g. en, nl, de). Leave empty for default.",
      "type": "text",
      "required": false,
      "placeholder": "en",
      "validation": "string|max:16",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "reforge_captcha_min_score",
      "constant": "REFORGE_CAPTCHA_MIN_SCORE",
      "description": "Minimum reForge Captcha verify score (0.0–1.0) when the verify API returns a score (stricter = higher)",
      "type": "text",
      "required": true,
      "placeholder": "0.5",
      "validation": "required|string|max:10",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "registration_enabled",
      "constant": "REGISTRATION_ENABLED",
      "description": "Can users register themselves?",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "registration_require_email_verification",
      "constant": "REGISTRATION_REQUIRE_EMAIL_VERIFICATION",
      "description": "Require users to verify their email before they can log in after registration.",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "registration_device_limit_enabled",
      "constant": "REGISTRATION_DEVICE_LIMIT_ENABLED",
      "description": "Block new registrations when a browser/device already has the maximum number of panel accounts.",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "registration_device_max_accounts",
      "constant": "REGISTRATION_DEVICE_MAX_ACCOUNTS",
      "description": "Maximum number of accounts allowed per browser/device before registration is blocked (main account is the oldest account seen on that device).",
      "type": "number",
      "required": true,
      "placeholder": "1",
      "validation": "required|integer|min:1|max:10",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "email_domain_blocking_enabled",
      "constant": "EMAIL_DOMAIN_BLOCKING_ENABLED",
      "description": "When enabled, registration and email changes are rejected if the address domain matches a row in Admin → Blocked email domains (suffix match). Manage the list on that page.",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "abuseipdb_enabled",
      "constant": "ABUSEIPDB_ENABLED",
      "description": "Enable AbuseIPDB integration for registration checks, user IP scanning, and optional reporting when banning users. Get an API key at https://www.abuseipdb.com/.",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "abuseipdb_api_key",
      "constant": "ABUSEIPDB_API_KEY",
      "description": "AbuseIPDB API key (stored encrypted). Required when AbuseIPDB is enabled.",
      "type": "password",
      "required": false,
      "placeholder": "Enter API key to change",
      "validation": "string|max:255",
      "options": [],
      "category": "security",
      "sensitive": true
    },
    {
      "key": "abuseipdb_check_on_register",
      "constant": "ABUSEIPDB_CHECK_ON_REGISTER",
      "description": "Check a registering user\\",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "abuseipdb_min_confidence_score",
      "constant": "ABUSEIPDB_MIN_CONFIDENCE_SCORE",
      "description": "Minimum AbuseIPDB abuse confidence score (0-100) to treat an IP as reported. AbuseIPDB recommends 75-100 for blocking.",
      "type": "number",
      "required": true,
      "placeholder": "75",
      "validation": "required|integer|min:0|max:100",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "abuseipdb_max_age_days",
      "constant": "ABUSEIPDB_MAX_AGE_DAYS",
      "description": "Only consider AbuseIPDB reports from the last N days when checking an IP (1-365).",
      "type": "number",
      "required": true,
      "placeholder": "90",
      "validation": "required|integer|min:1|max:365",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "abuseipdb_register_action",
      "constant": "ABUSEIPDB_REGISTER_ACTION",
      "description": "What to do when a registering IP meets the confidence score threshold.",
      "type": "select",
      "required": true,
      "placeholder": "block",
      "validation": "required|string|max:32",
      "options": [
        "block",
        "log",
        "auto_ban"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "require_two_fa_admins",
      "constant": "REQUIRE_TWO_FA_ADMINS",
      "description": "Require two-factor authentication for admins",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "avatar_provider",
      "constant": "AVATAR_PROVIDER",
      "description": "Default avatar provider for users without a custom profile picture",
      "type": "select",
      "required": true,
      "placeholder": "gravatar",
      "validation": "required|string|max:255",
      "options": [
        "gravatar",
        "panel_logo",
        "ui_avatars",
        "robohash",
        "dicebear",
        "custom"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "avatar_custom_url",
      "constant": "AVATAR_CUSTOM_URL",
      "description": "Custom avatar URL template (only used when avatar provider is custom). Placeholders: {email}, {username}, {name}, {hash}, {app_url}",
      "type": "text",
      "required": false,
      "placeholder": "https://example.com/avatar/{hash}",
      "validation": "nullable|string|max:2048",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_avatar_change",
      "constant": "USER_ALLOW_AVATAR_CHANGE",
      "description": "Allow users to change their avatar",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_username_change",
      "constant": "USER_ALLOW_USERNAME_CHANGE",
      "description": "Allow users to change their username",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_email_change",
      "constant": "USER_ALLOW_EMAIL_CHANGE",
      "description": "Allow users to change their email address",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_first_name_change",
      "constant": "USER_ALLOW_FIRST_NAME_CHANGE",
      "description": "Allow users to change their first name",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_last_name_change",
      "constant": "USER_ALLOW_LAST_NAME_CHANGE",
      "description": "Allow users to change their last name",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_api_keys_create",
      "constant": "USER_ALLOW_API_KEYS_CREATE",
      "description": "Allow users to create API keys",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_allow_account_deletion",
      "constant": "USER_ALLOW_ACCOUNT_DELETION",
      "description": "Allow users to permanently delete their own account",
      "type": "select",
      "required": true,
      "placeholder": "false",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_account_deletion_mode",
      "constant": "USER_ACCOUNT_DELETION_MODE",
      "description": "How account deletions are processed: instant, delayed, or after active services expire",
      "type": "select",
      "required": true,
      "placeholder": "instant",
      "validation": "required|string|max:64",
      "options": [
        "instant",
        "delayed",
        "after_services"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_account_deletion_delay_days",
      "constant": "USER_ACCOUNT_DELETION_DELAY_DAYS",
      "description": "Days to wait before hard-deleting when mode is delayed (1-365)",
      "type": "text",
      "required": true,
      "placeholder": "7",
      "validation": "required|string|max:10",
      "options": [],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_account_deletion_verify_2fa",
      "constant": "USER_ACCOUNT_DELETION_VERIFY_2FA",
      "description": "Require two-factor authentication to confirm account deletion",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    },
    {
      "key": "user_account_deletion_verify_email_otp",
      "constant": "USER_ACCOUNT_DELETION_VERIFY_EMAIL_OTP",
      "description": "Require email one-time password to confirm account deletion",
      "type": "select",
      "required": true,
      "placeholder": "true",
      "validation": "required|string|max:255",
      "options": [
        "true",
        "false"
      ],
      "category": "security",
      "sensitive": false
    }
  ]
}
