From 70e6fa382b5df6fb9a787601e629154d23e05d7e Mon Sep 17 00:00:00 2001 From: 3252a8 <3252a8@proton.me> Date: Tue, 2 Jun 2026 19:18:11 +0300 Subject: [PATCH] fix(docs-demo): sync admin settings sections with manifest The demo Settings screen was fed by a frozen snapshot baked into the externally generated demoDataset.js, so it drifted from the real manifest: the Remnawave Panel (plus System and Migrations) sections were missing and trial/checkout/common still showed as top-level sections instead of subsections. Generate frontend/src/lib/webapp/settingsManifest.generated.json from manifest_payload() (the same source the live /admin/settings endpoint uses) via scripts/export_settings_manifest.py, and build the demo section structure from it, overlaying realistic demo values per field key. A pytest drift guard fails if the Python manifest changes without regenerating the snapshot, so the demo stays in sync going forward. --- frontend/src/lib/webapp/mockApi.js | 44 +- .../webapp/settingsManifest.generated.json | 5469 +++++++++++++++++ scripts/export_settings_manifest.py | 96 + tests/test_settings_manifest_demo_sync.py | 51 + 4 files changed, 5651 insertions(+), 9 deletions(-) create mode 100644 frontend/src/lib/webapp/settingsManifest.generated.json create mode 100644 scripts/export_settings_manifest.py create mode 100644 tests/test_settings_manifest_demo_sync.py diff --git a/frontend/src/lib/webapp/mockApi.js b/frontend/src/lib/webapp/mockApi.js index cfbdf45..97ef8ea 100644 --- a/frontend/src/lib/webapp/mockApi.js +++ b/frontend/src/lib/webapp/mockApi.js @@ -1,5 +1,6 @@ import { DEV_MOCK } from "./previewMock.js"; import { DEMO_DATASET } from "./demoDataset.js"; +import SETTINGS_MANIFEST_SECTIONS from "./settingsManifest.generated.json"; import { withDemoAvatar, withDemoAvatarDetail, withDemoAvatarTicket } from "./demoAvatars.js"; const DEMO_LANGUAGE_STORAGE_KEY = "rw_minishop_demo_language"; @@ -605,18 +606,43 @@ function filterDemoSupportTickets(items, params) { return out; } +function demoSettingsValuesByKey() { + const map = new Map(); + for (const section of DEMO_DATASET.settingsSections || []) { + for (const field of section.fields || []) { + map.set(field.key, field); + } + } + return map; +} + function demoSettingsSections(clone) { - const sections = clone(DEMO_DATASET.settingsSections || []); + // Section/field structure comes from the manifest snapshot generated off the + // Python source of truth (scripts/export_settings_manifest.py), so the demo + // stays in sync with the real admin. Realistic values are overlaid per field + // key from the dump-based dataset; fields absent there (e.g. a freshly added + // section) simply show their placeholders. + const demoValues = demoSettingsValuesByKey(); + const sections = clone(SETTINGS_MANIFEST_SECTIONS); for (const section of sections) { for (const field of section.fields || []) { - if (!demoSettingsChanges.has(field.key)) continue; - const change = demoSettingsChanges.get(field.key); - if (change.deleted) { - field.value = field.default ?? ""; - field.overridden = false; - } else { - field.value = change.value; - field.overridden = true; + const demoField = demoValues.get(field.key); + if (demoField) { + if ("value" in demoField) field.value = demoField.value; + if ("overridden" in demoField) field.overridden = demoField.overridden; + if ("updated_at" in demoField) field.updated_at = demoField.updated_at; + if ("source" in demoField) field.source = demoField.source; + if (field.secret && "has_value" in demoField) field.has_value = demoField.has_value; + } + if (demoSettingsChanges.has(field.key)) { + const change = demoSettingsChanges.get(field.key); + if (change.deleted) { + field.value = field.default ?? ""; + field.overridden = false; + } else { + field.value = change.value; + field.overridden = true; + } } } } diff --git a/frontend/src/lib/webapp/settingsManifest.generated.json b/frontend/src/lib/webapp/settingsManifest.generated.json new file mode 100644 index 0000000..2c40773 --- /dev/null +++ b/frontend/src/lib/webapp/settingsManifest.generated.json @@ -0,0 +1,5469 @@ +[ + { + "id": "general", + "order": 1, + "fields": [ + { + "key": "WEBAPP_TITLE", + "type": "string", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Web App title", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_title_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": "admin_settings_field_webapp_title_placeholder", + "placeholder": "My subscription", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "DEFAULT_LANGUAGE", + "type": "string", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Язык по умолчанию", + "description": "Используется для приветственных сообщений и публичных страниц.", + "i18n_label_key": "admin_settings_field_default_language_label", + "i18n_description_key": "admin_settings_field_default_language_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "DEFAULT_CURRENCY_SYMBOL", + "type": "string", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Валюта", + "description": "Например, RUB, USD, EUR.", + "i18n_label_key": "admin_settings_field_default_currency_symbol_label", + "i18n_description_key": "admin_settings_field_default_currency_symbol_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": "admin_settings_field_default_currency_symbol_placeholder", + "placeholder": "RUB", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_LINK", + "type": "url", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Ссылка поддержки", + "description": "Куда вести пользователей за помощью.", + "i18n_label_key": "admin_settings_field_support_link_label", + "i18n_description_key": "admin_settings_field_support_link_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SERVER_STATUS_URL", + "type": "url", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Ссылка на статус серверов", + "description": "", + "i18n_label_key": "admin_settings_field_server_status_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TERMS_OF_SERVICE_URL", + "type": "url", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Условия использования", + "description": "", + "i18n_label_key": "admin_settings_field_terms_of_service_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PRIVACY_POLICY_URL", + "type": "url", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Политика конфиденциальности", + "description": "", + "i18n_label_key": "admin_settings_field_privacy_policy_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "USER_AGREEMENT_URL", + "type": "url", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Пользовательское соглашение", + "description": "", + "i18n_label_key": "admin_settings_field_user_agreement_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "DISABLE_WELCOME_MESSAGE", + "type": "bool", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Скрыть приветствие /start", + "description": "", + "i18n_label_key": "admin_settings_field_disable_welcome_message_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "START_COMMAND_DESCRIPTION", + "type": "string", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Описание /start", + "description": "", + "i18n_label_key": "admin_settings_field_start_command_description_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REQUIRED_CHANNEL_ID", + "type": "int", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "ID обязательного канала", + "description": "Telegram ID канала для проверки подписки. Если бот видит канал, ссылка кнопки будет получена автоматически.", + "i18n_label_key": "admin_settings_field_required_channel_id_label", + "i18n_description_key": "admin_settings_field_required_channel_id_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REQUIRED_CHANNEL_LINK", + "type": "string", + "section": "general", + "section_order": 1, + "subsection": null, + "label": "Ссылка на канал", + "description": "Необязательно: публичный @username или invite-link, если ссылку нельзя получить по ID канала.", + "i18n_label_key": "admin_settings_field_required_channel_link_label", + "i18n_description_key": "admin_settings_field_required_channel_link_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "appearance", + "order": 2, + "fields": [ + { + "key": "SUBSCRIPTION_MINI_APP_URL", + "type": "url", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Публичный URL Mini App", + "description": "Например, https://app.example.com/.", + "i18n_label_key": "admin_settings_field_subscription_mini_app_url_label", + "i18n_description_key": "admin_settings_field_subscription_mini_app_url_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_PRIMARY_COLOR", + "type": "color", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Основной цвет", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_primary_color_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": "admin_settings_field_webapp_primary_color_placeholder", + "placeholder": "#00fe7a", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_LOGO_USE_EMOJI", + "type": "bool", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Использовать эмоджи-логотип", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_logo_use_emoji_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_LOGO_URL", + "type": "url", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "URL логотипа", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_logo_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_LOGO_EMOJI", + "type": "string", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Эмоджи-логотип", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": "admin_settings_field_webapp_logo_emoji_placeholder", + "placeholder": "🫥", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_LOGO_EMOJI_FONT", + "type": "string", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Шрифт эмоджи-логотипа", + "description": "Выберите шрифт для отображения эмодзи-логотипа", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_label", + "i18n_description_key": "admin_settings_field_webapp_logo_emoji_font_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "choices": [ + { + "value": "system", + "label": "Системный (по умолчанию)", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_system" + }, + { + "value": "noto-color", + "label": "Noto Color Emoji", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_noto_color" + }, + { + "value": "noto-color-animated", + "label": "Noto Color Emoji Animated", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_noto_color_animated" + }, + { + "value": "noto-emoji", + "label": "Noto Emoji", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_noto_emoji" + }, + { + "value": "twemoji", + "label": "Twitter Emoji", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_twemoji" + }, + { + "value": "openmoji", + "label": "OpenMoji", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_openmoji" + }, + { + "value": "apple", + "label": "Apple Color Emoji (local)", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_apple" + }, + { + "value": "segoe", + "label": "Segoe UI Emoji (local)", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_segoe" + }, + { + "value": "noto-local", + "label": "Noto Emoji (local)", + "i18n_label_key": "admin_settings_field_webapp_logo_emoji_font_choice_noto_local" + } + ], + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_FAVICON_USE_CUSTOM", + "type": "bool", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Использовать отдельную favicon", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_favicon_use_custom_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_FAVICON_URL", + "type": "url", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "URL отдельной favicon", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_favicon_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_LOGO_FAVICON_URL", + "type": "url", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Favicon из логотипа", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_logo_favicon_url_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "WEBAPP_ENABLED", + "type": "bool", + "section": "appearance", + "section_order": 2, + "subsection": null, + "label": "Web App включён", + "description": "", + "i18n_label_key": "admin_settings_field_webapp_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "remnawave", + "order": 3, + "fields": [ + { + "key": "PANEL_API_URL", + "type": "url", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "URL API Remnawave", + "description": "Например, https://panel.example.com/api.", + "i18n_label_key": "admin_settings_field_panel_api_url_label", + "i18n_description_key": "admin_settings_field_panel_api_url_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PANEL_API_KEY", + "type": "string", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "API-ключ Remnawave", + "description": "Секретный ключ API панели.", + "i18n_label_key": "admin_settings_field_panel_api_key_label", + "i18n_description_key": "admin_settings_field_panel_api_key_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false + }, + { + "key": "PANEL_API_TOTAL_TIMEOUT_SECONDS", + "type": "float", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "Panel API total timeout", + "description": "Maximum total time for one Remnawave API request, in seconds.", + "i18n_label_key": "admin_settings_field_panel_api_total_timeout_seconds_label", + "i18n_description_key": "admin_settings_field_panel_api_total_timeout_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PANEL_API_CONNECT_TIMEOUT_SECONDS", + "type": "float", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "Panel API connect timeout", + "description": "Maximum time to get or open a Remnawave API connection, in seconds.", + "i18n_label_key": "admin_settings_field_panel_api_connect_timeout_seconds_label", + "i18n_description_key": "admin_settings_field_panel_api_connect_timeout_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PANEL_API_SOCK_CONNECT_TIMEOUT_SECONDS", + "type": "float", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "Panel API socket connect timeout", + "description": "Maximum TCP/TLS connection time for Remnawave API, in seconds.", + "i18n_label_key": "admin_settings_field_panel_api_sock_connect_timeout_seconds_label", + "i18n_description_key": "admin_settings_field_panel_api_sock_connect_timeout_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PANEL_API_SOCK_READ_TIMEOUT_SECONDS", + "type": "float", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "Panel API socket read timeout", + "description": "Maximum time to wait for response data from Remnawave API, in seconds.", + "i18n_label_key": "admin_settings_field_panel_api_sock_read_timeout_seconds_label", + "i18n_description_key": "admin_settings_field_panel_api_sock_read_timeout_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PANEL_WEBHOOK_SECRET", + "type": "string", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "Секрет вебхуков Remnawave", + "description": "Используется для проверки входящих вебхуков панели.", + "i18n_label_key": "admin_settings_field_panel_webhook_secret_label", + "i18n_description_key": "admin_settings_field_panel_webhook_secret_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "webhook_path": "/webhook/panel", + "webhook_requires_base_url": true, + "provider_id": "remnawave", + "webhook_hint_i18n_key": "admin_settings_panel_webhook_url_hint", + "webhook_hint": "Use this URL as WEBHOOK_URL in Remnawave Panel.", + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "USER_SQUAD_UUIDS", + "type": "string", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "Internal Squads по умолчанию", + "description": "UUID через запятую для legacy-режима без JSON-каталога тарифов.", + "i18n_label_key": "admin_settings_field_user_squad_uuids_label", + "i18n_description_key": "admin_settings_field_user_squad_uuids_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "USER_EXTERNAL_SQUAD_UUID", + "type": "string", + "section": "remnawave", + "section_order": 3, + "subsection": null, + "label": "External Squad по умолчанию", + "description": "Необязательный UUID External Squad для новых пользователей.", + "i18n_label_key": "admin_settings_field_user_external_squad_uuid_label", + "i18n_description_key": "admin_settings_field_user_external_squad_uuid_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "payments", + "order": 4, + "fields": [ + { + "key": "SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "checkout", + "label": "Показывать описание подписки", + "description": "Текст появится перед выбором срока покупки или продления.", + "i18n_label_key": "admin_settings_field_subscription_purchase_description_enabled_label", + "i18n_description_key": "admin_settings_field_subscription_purchase_description_enabled_description", + "i18n_subsection_key": "admin_settings_subsection_checkout", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_PURCHASE_DESCRIPTION_RU", + "type": "text", + "section": "payments", + "section_order": 4, + "subsection": "checkout", + "label": "Описание подписки (RU)", + "description": "Русская версия текста на этапе оплаты.", + "i18n_label_key": "admin_settings_field_subscription_purchase_description_ru_label", + "i18n_description_key": "admin_settings_field_subscription_purchase_description_ru_description", + "i18n_subsection_key": "admin_settings_subsection_checkout", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_PURCHASE_DESCRIPTION_EN", + "type": "text", + "section": "payments", + "section_order": 4, + "subsection": "checkout", + "label": "Описание подписки (EN)", + "description": "Английская версия текста на этапе оплаты.", + "i18n_label_key": "admin_settings_field_subscription_purchase_description_en_label", + "i18n_description_key": "admin_settings_field_subscription_purchase_description_en_description", + "i18n_subsection_key": "admin_settings_subsection_checkout", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "common", + "label": "Telegram Stars", + "description": "", + "i18n_label_key": "admin_settings_field_stars_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_common", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "STARS_ADMIN_ONLY_ENABLED", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "common", + "label": "Telegram Stars admin-only", + "description": "Shows Telegram Stars only to users from ADMIN_IDS. Payment callbacks remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_common", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "STARS_ENABLED", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PAYMENT_METHODS_ORDER", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "common", + "label": "Порядок методов оплаты", + "description": "Через запятую: severpay,freekassa,yookassa,platega,stars,cryptopay,heleket", + "i18n_label_key": "admin_settings_field_payment_methods_order_label", + "i18n_description_key": "admin_settings_field_payment_methods_order_description", + "i18n_subsection_key": "admin_settings_subsection_common", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "FREEKASSA_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Включена", + "description": "", + "i18n_label_key": "admin_settings_field_freekassa_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "FREEKASSA_ADMIN_ONLY_ENABLED", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_MERCHANT_ID", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Merchant ID", + "description": "", + "i18n_label_key": "admin_settings_field_freekassa_merchant_id_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_FIRST_SECRET", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "First secret", + "description": "", + "i18n_label_key": "admin_settings_field_freekassa_first_secret_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_SECOND_SECRET", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Second secret", + "description": "", + "i18n_label_key": "admin_settings_field_freekassa_second_secret_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_API_KEY", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "API key", + "description": "", + "i18n_label_key": "admin_settings_field_freekassa_api_key_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_PAYMENT_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Payment URL", + "description": "", + "i18n_label_key": "admin_settings_field_freekassa_payment_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_freekassa_payment_url_placeholder", + "placeholder": "https://pay.freekassa.ru/", + "optional": true, + "secret": false, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_PAYMENT_METHOD_ID", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Payment method ID", + "description": "See https://merchant.freekassa.net/settings/currencies", + "i18n_label_key": "admin_settings_field_freekassa_payment_method_id_label", + "i18n_description_key": "admin_settings_field_freekassa_payment_method_id_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_PAYMENT_IP", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Server IP", + "description": "Public IP address reported to FreeKassa.", + "i18n_label_key": "admin_settings_field_freekassa_payment_ip_label", + "i18n_description_key": "admin_settings_field_freekassa_payment_ip_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_TRUSTED_IPS", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Trusted IPs", + "description": "Comma-separated IP addresses accepted for FreeKassa webhooks.", + "i18n_label_key": "admin_settings_field_freekassa_trusted_ips_label", + "i18n_description_key": "admin_settings_field_freekassa_trusted_ips_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_FREEKASSA_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_freekassa_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_freekassa_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_payment_freekassa_webapp_label_ru_placeholder", + "placeholder": "FreeKassa / СБП", + "optional": true, + "secret": false, + "default": "FreeKassa / СБП", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_FREEKASSA_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_freekassa_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_freekassa_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_payment_freekassa_webapp_label_en_placeholder", + "placeholder": "FreeKassa / SBP", + "optional": true, + "secret": false, + "default": "FreeKassa / SBP", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_FREEKASSA_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_freekassa_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_freekassa_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_payment_freekassa_webapp_icon_placeholder", + "placeholder": "Smartphone", + "optional": true, + "secret": false, + "default": "Smartphone", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_FREEKASSA_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_freekassa_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_freekassa_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_payment_freekassa_telegram_label_ru_placeholder", + "placeholder": "СБП", + "optional": true, + "secret": false, + "default": "СБП", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_FREEKASSA_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_freekassa_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_freekassa_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_payment_freekassa_telegram_label_en_placeholder", + "placeholder": "SBP", + "optional": true, + "secret": false, + "default": "SBP", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_FREEKASSA_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_freekassa_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_freekassa_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": "admin_settings_field_payment_freekassa_telegram_emoji_placeholder", + "placeholder": "📱", + "optional": true, + "secret": false, + "default": "📱", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "FREEKASSA_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "FreeKassa", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_freekassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "FREEKASSA_ENABLED", + "provider_id": "freekassa", + "provider_label": "FreeKassa", + "webhook_provider_id": "freekassa", + "webhook_path": "/webhook/freekassa", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Включена", + "description": "", + "i18n_label_key": "admin_settings_field_platega_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_BASE_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Base URL", + "description": "", + "i18n_label_key": "admin_settings_field_platega_base_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_platega_base_url_placeholder", + "placeholder": "https://app.platega.io", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_MERCHANT_ID", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Merchant ID", + "description": "", + "i18n_label_key": "admin_settings_field_platega_merchant_id_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_SECRET", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Secret", + "description": "", + "i18n_label_key": "admin_settings_field_platega_secret_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_PAYMENT_METHOD", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Метод оплаты (legacy)", + "description": "", + "i18n_label_key": "admin_settings_field_platega_payment_method_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_SBP_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "SBP-кнопка", + "description": "", + "i18n_label_key": "admin_settings_field_platega_sbp_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "PLATEGA_SBP_ADMIN_ONLY_ENABLED", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_SBP_METHOD", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "SBP method ID", + "description": "", + "i18n_label_key": "admin_settings_field_platega_sbp_method_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_CRYPTO_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Crypto-кнопка", + "description": "", + "i18n_label_key": "admin_settings_field_platega_crypto_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "PLATEGA_CRYPTO_ADMIN_ONLY_ENABLED", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_CRYPTO_METHOD", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Crypto method ID", + "description": "", + "i18n_label_key": "admin_settings_field_platega_crypto_method_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_SUPPORTED_CURRENCIES", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Supported currencies", + "description": "Comma-separated payment currencies enabled for your Platega merchant. Public docs expose currency per method/limits but do not publish a fixed global list.", + "i18n_label_key": "admin_settings_field_platega_supported_currencies_label", + "i18n_description_key": "admin_settings_field_platega_supported_currencies_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_platega_supported_currencies_placeholder", + "placeholder": "RUB", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_RETURN_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Return URL", + "description": "", + "i18n_label_key": "admin_settings_field_platega_return_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_FAILED_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Failed URL", + "description": "", + "i18n_label_key": "admin_settings_field_platega_failed_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_SBP_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_platega_sbp_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_platega_sbp_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_sbp_webapp_label_ru_placeholder", + "placeholder": "Оплата картой (СБП)", + "optional": true, + "secret": false, + "default": "Оплата картой (СБП)", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_SBP_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_platega_sbp_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_platega_sbp_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_sbp_webapp_label_en_placeholder", + "placeholder": "Pay with card (SBP)", + "optional": true, + "secret": false, + "default": "Pay with card (SBP)", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_SBP_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_platega_sbp_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_platega_sbp_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_sbp_webapp_icon_placeholder", + "placeholder": "CreditCard", + "optional": true, + "secret": false, + "default": "CreditCard", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_SBP_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_platega_sbp_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_platega_sbp_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_sbp_telegram_label_ru_placeholder", + "placeholder": "Оплата через СБП", + "optional": true, + "secret": false, + "default": "Оплата через СБП", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_SBP_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_platega_sbp_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_platega_sbp_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_sbp_telegram_label_en_placeholder", + "placeholder": "Pay via SBP", + "optional": true, + "secret": false, + "default": "Pay via SBP", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_SBP_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_platega_sbp_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_platega_sbp_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_sbp_telegram_emoji_placeholder", + "placeholder": "🏦", + "optional": true, + "secret": false, + "default": "🏦", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_SBP_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "PLATEGA_SBP_ENABLED", + "provider_id": "platega_sbp", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_CRYPTO_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_platega_crypto_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_platega_crypto_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_crypto_webapp_label_ru_placeholder", + "placeholder": "Крипта", + "optional": true, + "secret": false, + "default": "Крипта", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_CRYPTO_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_platega_crypto_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_platega_crypto_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_crypto_webapp_label_en_placeholder", + "placeholder": "Crypto", + "optional": true, + "secret": false, + "default": "Crypto", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_CRYPTO_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_platega_crypto_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_platega_crypto_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_crypto_webapp_icon_placeholder", + "placeholder": "Bitcoin", + "optional": true, + "secret": false, + "default": "Bitcoin", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_CRYPTO_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_platega_crypto_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_platega_crypto_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_crypto_telegram_label_ru_placeholder", + "placeholder": "Оплата криптой", + "optional": true, + "secret": false, + "default": "Оплата криптой", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_CRYPTO_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_platega_crypto_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_platega_crypto_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_crypto_telegram_label_en_placeholder", + "placeholder": "Pay with crypto", + "optional": true, + "secret": false, + "default": "Pay with crypto", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_PLATEGA_CRYPTO_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_platega_crypto_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_platega_crypto_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": "admin_settings_field_payment_platega_crypto_telegram_emoji_placeholder", + "placeholder": "🪙", + "optional": true, + "secret": false, + "default": "🪙", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PLATEGA_CRYPTO_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Platega", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_platega", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "PLATEGA_CRYPTO_ENABLED", + "provider_id": "platega_crypto", + "provider_label": "Platega", + "webhook_provider_id": "platega_sbp", + "webhook_path": "/webhook/platega", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Включена", + "description": "", + "i18n_label_key": "admin_settings_field_severpay_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "SEVERPAY_ADMIN_ONLY_ENABLED", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_MID", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "MID", + "description": "", + "i18n_label_key": "admin_settings_field_severpay_mid_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_TOKEN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Token", + "description": "", + "i18n_label_key": "admin_settings_field_severpay_token_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_BASE_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Base URL", + "description": "", + "i18n_label_key": "admin_settings_field_severpay_base_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_severpay_base_url_placeholder", + "placeholder": "https://severpay.io/api/merchant", + "optional": true, + "secret": false, + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_RETURN_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Return URL", + "description": "", + "i18n_label_key": "admin_settings_field_severpay_return_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_LIFETIME_MINUTES", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Payment link lifetime (minutes)", + "description": "30..4320; leave empty for the SeverPay default.", + "i18n_label_key": "admin_settings_field_severpay_lifetime_minutes_label", + "i18n_description_key": "admin_settings_field_severpay_lifetime_minutes_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 30, + "max": 4320, + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_SUPPORTED_CURRENCIES", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Supported currencies", + "description": "Comma-separated currencies enabled for your SeverPay merchant. The public PayIn docs show USD examples but do not publish a fixed global list.", + "i18n_label_key": "admin_settings_field_severpay_supported_currencies_label", + "i18n_description_key": "admin_settings_field_severpay_supported_currencies_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_severpay_supported_currencies_placeholder", + "placeholder": "RUB,USD", + "optional": true, + "secret": false, + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_SEVERPAY_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_severpay_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_severpay_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_payment_severpay_webapp_label_ru_placeholder", + "placeholder": "SeverPay", + "optional": true, + "secret": false, + "default": "SeverPay", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_SEVERPAY_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_severpay_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_severpay_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_payment_severpay_webapp_label_en_placeholder", + "placeholder": "SeverPay", + "optional": true, + "secret": false, + "default": "SeverPay", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_SEVERPAY_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_severpay_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_severpay_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_payment_severpay_webapp_icon_placeholder", + "placeholder": "CreditCard", + "optional": true, + "secret": false, + "default": "CreditCard", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_SEVERPAY_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_severpay_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_severpay_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_payment_severpay_telegram_label_ru_placeholder", + "placeholder": "SeverPay", + "optional": true, + "secret": false, + "default": "SeverPay", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_SEVERPAY_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_severpay_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_severpay_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_payment_severpay_telegram_label_en_placeholder", + "placeholder": "SeverPay", + "optional": true, + "secret": false, + "default": "SeverPay", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_SEVERPAY_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_severpay_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_severpay_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": "admin_settings_field_payment_severpay_telegram_emoji_placeholder", + "placeholder": "💳", + "optional": true, + "secret": false, + "default": "💳", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "SEVERPAY_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "SeverPay", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_severpay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "SEVERPAY_ENABLED", + "provider_id": "severpay", + "provider_label": "SeverPay", + "webhook_provider_id": "severpay", + "webhook_path": "/webhook/severpay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Enabled", + "description": "", + "i18n_label_key": "admin_settings_field_wata_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "WATA_ADMIN_ONLY_ENABLED", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_API_TOKEN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "API token", + "description": "", + "i18n_label_key": "admin_settings_field_wata_api_token_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "WATA_BASE_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Base URL", + "description": "", + "i18n_label_key": "admin_settings_field_wata_base_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_wata_base_url_placeholder", + "placeholder": "https://api.wata.pro/api/h2h", + "optional": true, + "secret": false, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_RETURN_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Return URL", + "description": "", + "i18n_label_key": "admin_settings_field_wata_return_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_FAILED_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Failed URL", + "description": "", + "i18n_label_key": "admin_settings_field_wata_failed_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_LINK_TTL_MINUTES", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Payment link lifetime (minutes)", + "description": "15..43200; default 15 minutes. Wata requires more than 10 minutes and allows up to 30 days.", + "i18n_label_key": "admin_settings_field_wata_link_ttl_minutes_label", + "i18n_description_key": "admin_settings_field_wata_link_ttl_minutes_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 15, + "max": 43200, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_WEBHOOK_VERIFY_SIGNATURE", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Verify webhook signature", + "description": "", + "i18n_label_key": "admin_settings_field_wata_webhook_verify_signature_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_PUBLIC_KEY", + "type": "text", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Webhook public key", + "description": "Optional. If empty, the backend fetches it from Wata.", + "i18n_label_key": "admin_settings_field_wata_public_key_label", + "i18n_description_key": "admin_settings_field_wata_public_key_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "WATA_TRUSTED_IPS", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Trusted IPs", + "description": "Comma-separated IP addresses accepted for Wata webhooks.", + "i18n_label_key": "admin_settings_field_wata_trusted_ips_label", + "i18n_description_key": "admin_settings_field_wata_trusted_ips_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_WATA_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_wata_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_wata_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_payment_wata_webapp_label_ru_placeholder", + "placeholder": "Wata", + "optional": true, + "secret": false, + "default": "Wata", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_WATA_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_wata_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_wata_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_payment_wata_webapp_label_en_placeholder", + "placeholder": "Wata", + "optional": true, + "secret": false, + "default": "Wata", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_WATA_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_wata_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_wata_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_payment_wata_webapp_icon_placeholder", + "placeholder": "WalletCards", + "optional": true, + "secret": false, + "default": "WalletCards", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_WATA_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_wata_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_wata_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_payment_wata_telegram_label_ru_placeholder", + "placeholder": "Wata", + "optional": true, + "secret": false, + "default": "Wata", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_WATA_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_wata_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_wata_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_payment_wata_telegram_label_en_placeholder", + "placeholder": "Wata", + "optional": true, + "secret": false, + "default": "Wata", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_WATA_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_wata_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_wata_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": "admin_settings_field_payment_wata_telegram_emoji_placeholder", + "placeholder": "💳", + "optional": true, + "secret": false, + "default": "💳", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "WATA_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Wata", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_wata", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "WATA_ENABLED", + "provider_id": "wata", + "provider_label": "Wata", + "webhook_provider_id": "wata", + "webhook_path": "/webhook/wata", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Включена", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "YOOKASSA_ADMIN_ONLY_ENABLED", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_SHOP_ID", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Shop ID", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_shop_id_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_SECRET_KEY", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Secret key", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_secret_key_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_RETURN_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Return URL", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_return_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_DEFAULT_RECEIPT_EMAIL", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Email для чека по умолчанию", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_default_receipt_email_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_VAT_CODE", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "VAT code", + "description": "1..6 в зависимости от системы налогообложения", + "i18n_label_key": "admin_settings_field_yookassa_vat_code_label", + "i18n_description_key": "admin_settings_field_yookassa_vat_code_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 1, + "max": 6, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_AUTOPAYMENTS_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Автоплатежи (recurring)", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_autopayments_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_AUTOPAYMENTS_REQUIRE_CARD_BINDING", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Принудительная привязка карты", + "description": "", + "i18n_label_key": "admin_settings_field_yookassa_autopayments_require_card_binding_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_YOOKASSA_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_yookassa_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_yookassa_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": "admin_settings_field_payment_yookassa_webapp_label_ru_placeholder", + "placeholder": "ЮKassa", + "optional": true, + "secret": false, + "default": "ЮKassa", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_YOOKASSA_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_yookassa_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_yookassa_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": "admin_settings_field_payment_yookassa_webapp_label_en_placeholder", + "placeholder": "YooKassa", + "optional": true, + "secret": false, + "default": "YooKassa", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_YOOKASSA_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_yookassa_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_yookassa_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": "admin_settings_field_payment_yookassa_webapp_icon_placeholder", + "placeholder": "CreditCard", + "optional": true, + "secret": false, + "default": "CreditCard", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_YOOKASSA_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_yookassa_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_yookassa_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": "admin_settings_field_payment_yookassa_telegram_label_ru_placeholder", + "placeholder": "ЮKassa", + "optional": true, + "secret": false, + "default": "ЮKassa", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_YOOKASSA_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_yookassa_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_yookassa_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": "admin_settings_field_payment_yookassa_telegram_label_en_placeholder", + "placeholder": "YooKassa", + "optional": true, + "secret": false, + "default": "YooKassa", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_YOOKASSA_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_yookassa_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_yookassa_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": "admin_settings_field_payment_yookassa_telegram_emoji_placeholder", + "placeholder": "💳", + "optional": true, + "secret": false, + "default": "💳", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "YOOKASSA_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "YooKassa", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_yookassa", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "YOOKASSA_ENABLED", + "provider_id": "yookassa", + "provider_label": "YooKassa", + "webhook_provider_id": "yookassa", + "webhook_path": "/webhook/yookassa", + "webhook_requires_base_url": true, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_STARS_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Telegram Stars", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_stars_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_stars_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_telegram_stars", + "i18n_placeholder_key": "admin_settings_field_payment_stars_webapp_label_ru_placeholder", + "placeholder": "Звёзды Telegram", + "optional": true, + "secret": false, + "default": "Звёзды Telegram", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PAYMENT_STARS_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Telegram Stars", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_stars_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_stars_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_telegram_stars", + "i18n_placeholder_key": "admin_settings_field_payment_stars_webapp_label_en_placeholder", + "placeholder": "Telegram Stars", + "optional": true, + "secret": false, + "default": "Telegram Stars", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PAYMENT_STARS_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "Telegram Stars", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_stars_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_stars_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_telegram_stars", + "i18n_placeholder_key": "admin_settings_field_payment_stars_webapp_icon_placeholder", + "placeholder": "Sparkles", + "optional": true, + "secret": false, + "default": "Sparkles", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PAYMENT_STARS_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Telegram Stars", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_stars_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_stars_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_telegram_stars", + "i18n_placeholder_key": "admin_settings_field_payment_stars_telegram_label_ru_placeholder", + "placeholder": "Звёзды Telegram", + "optional": true, + "secret": false, + "default": "Звёзды Telegram", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PAYMENT_STARS_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Telegram Stars", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_stars_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_stars_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_telegram_stars", + "i18n_placeholder_key": "admin_settings_field_payment_stars_telegram_label_en_placeholder", + "placeholder": "Telegram Stars", + "optional": true, + "secret": false, + "default": "Telegram Stars", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "PAYMENT_STARS_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Telegram Stars", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_stars_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_stars_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_telegram_stars", + "i18n_placeholder_key": "admin_settings_field_payment_stars_telegram_emoji_placeholder", + "placeholder": "🌟", + "optional": true, + "secret": false, + "default": "⭐", + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "CRYPTOPAY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Включена", + "description": "", + "i18n_label_key": "admin_settings_field_cryptopay_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "CRYPTOPAY_ADMIN_ONLY_ENABLED", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "CRYPTOPAY_TOKEN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Token", + "description": "", + "i18n_label_key": "admin_settings_field_cryptopay_token_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "CRYPTOPAY_NETWORK", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Network", + "description": "", + "i18n_label_key": "admin_settings_field_cryptopay_network_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_cryptopay_network_placeholder", + "placeholder": "mainnet", + "optional": true, + "secret": false, + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "CRYPTOPAY_CURRENCY_TYPE", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Currency type", + "description": "fiat or crypto.", + "i18n_label_key": "admin_settings_field_cryptopay_currency_type_label", + "i18n_description_key": "admin_settings_field_cryptopay_currency_type_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_cryptopay_currency_type_placeholder", + "placeholder": "fiat", + "optional": true, + "secret": false, + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "CRYPTOPAY_ASSET", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Asset", + "description": "", + "i18n_label_key": "admin_settings_field_cryptopay_asset_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_cryptopay_asset_placeholder", + "placeholder": "RUB", + "optional": true, + "secret": false, + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_CRYPTOPAY_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_cryptopay_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_cryptopay_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_payment_cryptopay_webapp_label_ru_placeholder", + "placeholder": "CryptoPay", + "optional": true, + "secret": false, + "default": "CryptoPay", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_CRYPTOPAY_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_cryptopay_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_cryptopay_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_payment_cryptopay_webapp_label_en_placeholder", + "placeholder": "CryptoPay", + "optional": true, + "secret": false, + "default": "CryptoPay", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_CRYPTOPAY_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_cryptopay_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_cryptopay_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_payment_cryptopay_webapp_icon_placeholder", + "placeholder": "Bitcoin", + "optional": true, + "secret": false, + "default": "Bitcoin", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_CRYPTOPAY_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_cryptopay_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_cryptopay_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_payment_cryptopay_telegram_label_ru_placeholder", + "placeholder": "CryptoBot", + "optional": true, + "secret": false, + "default": "CryptoBot", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_CRYPTOPAY_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_cryptopay_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_cryptopay_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_payment_cryptopay_telegram_label_en_placeholder", + "placeholder": "CryptoBot", + "optional": true, + "secret": false, + "default": "CryptoBot", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_CRYPTOPAY_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_cryptopay_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_cryptopay_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": "admin_settings_field_payment_cryptopay_telegram_emoji_placeholder", + "placeholder": "₿", + "optional": true, + "secret": false, + "default": "₿", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "CRYPTOPAY_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "CryptoPay", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_cryptopay", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "CRYPTOPAY_ENABLED", + "provider_id": "cryptopay", + "provider_label": "CryptoPay", + "webhook_provider_id": "cryptopay", + "webhook_path": "/webhook/cryptopay", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Enabled", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "HELEKET_ADMIN_ONLY_ENABLED", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_MERCHANT_ID", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Merchant ID", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_merchant_id_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_API_KEY", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Payment API key", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_api_key_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": true, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "has_value": false, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_BASE_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Base URL", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_base_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_heleket_base_url_placeholder", + "placeholder": "https://api.heleket.com", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_CURRENCY", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Invoice currency", + "description": "Fiat or crypto code (RUB, USD, USDT).", + "i18n_label_key": "admin_settings_field_heleket_currency_label", + "i18n_description_key": "admin_settings_field_heleket_currency_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_heleket_currency_placeholder", + "placeholder": "RUB", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_SUPPORTED_CURRENCIES", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Supported currencies", + "description": "Comma-separated invoice currencies allowed for Heleket in this shop. Heleket can reject unsupported codes per account/service.", + "i18n_label_key": "admin_settings_field_heleket_supported_currencies_label", + "i18n_description_key": "admin_settings_field_heleket_supported_currencies_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_heleket_supported_currencies_placeholder", + "placeholder": "RUB,USD,EUR,USDT,USDC,BTC,ETH,LTC,TON,TRX,BNB,BCH,DASH,DAI,DOGE,MATIC,SHIB,SOL,XMR,AVAX,BUSD,VERSE", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_TO_CURRENCY", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Target crypto", + "description": "Optional target cryptocurrency for conversion.", + "i18n_label_key": "admin_settings_field_heleket_to_currency_label", + "i18n_description_key": "admin_settings_field_heleket_to_currency_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_NETWORK", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Blockchain network", + "description": "Optional blockchain network code (tron, bsc, eth).", + "i18n_label_key": "admin_settings_field_heleket_network_label", + "i18n_description_key": "admin_settings_field_heleket_network_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_RETURN_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Return URL", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_return_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_SUCCESS_URL", + "type": "url", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Success URL", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_success_url_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_LIFETIME_SECONDS", + "type": "int", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Invoice lifetime (seconds)", + "description": "300..43200; Heleket defaults to 3600.", + "i18n_label_key": "admin_settings_field_heleket_lifetime_seconds_label", + "i18n_description_key": "admin_settings_field_heleket_lifetime_seconds_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 300, + "max": 43200, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_VERIFY_WEBHOOK_SIGNATURE", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Verify webhook signature", + "description": "", + "i18n_label_key": "admin_settings_field_heleket_verify_webhook_signature_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_TRUSTED_IPS", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Trusted IPs", + "description": "Comma-separated IP addresses accepted for Heleket webhooks.", + "i18n_label_key": "admin_settings_field_heleket_trusted_ips_label", + "i18n_description_key": "admin_settings_field_heleket_trusted_ips_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_HELEKET_WEBAPP_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "WebApp button text (RU)", + "description": "Custom Russian text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_heleket_webapp_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_heleket_webapp_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_payment_heleket_webapp_label_ru_placeholder", + "placeholder": "Heleket", + "optional": true, + "secret": false, + "default": "Heleket", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_HELEKET_WEBAPP_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "WebApp button text (EN)", + "description": "Custom English text shown in the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_heleket_webapp_label_en_label", + "i18n_description_key": "admin_settings_field_payment_heleket_webapp_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_payment_heleket_webapp_label_en_placeholder", + "placeholder": "Heleket", + "optional": true, + "secret": false, + "default": "Heleket", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_HELEKET_WEBAPP_ICON", + "type": "icon", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "WebApp button icon", + "description": "Lucide icon name rendered inside the Web App payment method button.", + "i18n_label_key": "admin_settings_field_payment_heleket_webapp_icon_label", + "i18n_description_key": "admin_settings_field_payment_heleket_webapp_icon_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_payment_heleket_webapp_icon_placeholder", + "placeholder": "Bitcoin", + "optional": true, + "secret": false, + "default": "Bitcoin", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_HELEKET_TELEGRAM_LABEL_RU", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Telegram button text (RU)", + "description": "Custom Russian text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_heleket_telegram_label_ru_label", + "i18n_description_key": "admin_settings_field_payment_heleket_telegram_label_ru_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_payment_heleket_telegram_label_ru_placeholder", + "placeholder": "Heleket", + "optional": true, + "secret": false, + "default": "Heleket", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_HELEKET_TELEGRAM_LABEL_EN", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Telegram button text (EN)", + "description": "Custom English text shown in Telegram bot payment buttons.", + "i18n_label_key": "admin_settings_field_payment_heleket_telegram_label_en_label", + "i18n_description_key": "admin_settings_field_payment_heleket_telegram_label_en_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_payment_heleket_telegram_label_en_placeholder", + "placeholder": "Heleket", + "optional": true, + "secret": false, + "default": "Heleket", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "PAYMENT_HELEKET_TELEGRAM_EMOJI", + "type": "string", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Telegram button emoji", + "description": "Emoji prepended to the Telegram bot payment button when customized.", + "i18n_label_key": "admin_settings_field_payment_heleket_telegram_emoji_label", + "i18n_description_key": "admin_settings_field_payment_heleket_telegram_emoji_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": "admin_settings_field_payment_heleket_telegram_emoji_placeholder", + "placeholder": "🪙", + "optional": true, + "secret": false, + "default": "🪙", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + }, + { + "key": "HELEKET_ADMIN_ONLY_ENABLED", + "type": "bool", + "section": "payments", + "section_order": 4, + "subsection": "Heleket", + "label": "Only for admins", + "description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.", + "i18n_label_key": "admin_settings_provider_admin_only_label", + "i18n_description_key": "admin_settings_provider_admin_only_description", + "i18n_subsection_key": "admin_settings_subsection_heleket", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "mutually_exclusive_key": "HELEKET_ENABLED", + "provider_id": "heleket", + "provider_label": "Heleket", + "webhook_provider_id": "heleket", + "webhook_path": "/webhook/heleket", + "webhook_requires_base_url": false, + "value": "", + "overridden": false, + "updated_at": null, + "webhook_base_url_configured": false + } + ] + }, + { + "id": "referral", + "order": 6, + "fields": [ + { + "key": "REFERRAL_ONE_BONUS_PER_REFEREE", + "type": "bool", + "section": "referral", + "section_order": 6, + "subsection": null, + "label": "Один бонус на приглашённого", + "description": "", + "i18n_label_key": "admin_settings_field_referral_one_bonus_per_referee_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_WELCOME_BONUS_DAYS", + "type": "int", + "section": "referral", + "section_order": 6, + "subsection": null, + "label": "Приветственный бонус (дней)", + "description": "", + "i18n_label_key": "admin_settings_field_referral_welcome_bonus_days_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LEGACY_REFS", + "type": "bool", + "section": "referral", + "section_order": 6, + "subsection": null, + "label": "Поддержка старых ref-ссылок", + "description": "", + "i18n_label_key": "admin_settings_field_legacy_refs_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "notifications", + "order": 7, + "fields": [ + { + "key": "SUBSCRIPTION_NOTIFICATIONS_ENABLED", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Включены уведомления о подписке", + "description": "", + "i18n_label_key": "admin_settings_field_subscription_notifications_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_EMAIL_NOTIFICATIONS_ENABLED", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Дублировать уведомления о подписке на email", + "description": "Письма отправляются только пользователям с привязанным email и рабочим SMTP.", + "i18n_label_key": "admin_settings_field_subscription_email_notifications_enabled_label", + "i18n_description_key": "admin_settings_field_subscription_email_notifications_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_NOTIFY_ON_EXPIRE", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Уведомлять об истечении", + "description": "", + "i18n_label_key": "admin_settings_field_subscription_notify_on_expire_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_NOTIFY_AFTER_EXPIRE", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Уведомлять после истечения", + "description": "", + "i18n_label_key": "admin_settings_field_subscription_notify_after_expire_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_NOTIFY_DAYS_BEFORE", + "type": "int", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "За сколько дней предупреждать", + "description": "", + "i18n_label_key": "admin_settings_field_subscription_notify_days_before_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_NOTIFY_HOURS_BEFORE", + "type": "int", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "За сколько часов предупреждать", + "description": "", + "i18n_label_key": "admin_settings_field_subscription_notify_hours_before_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "max": 23, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_NEW_USERS", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать новых пользователей", + "description": "", + "i18n_label_key": "admin_settings_field_log_new_users_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_PAYMENTS", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать платежи", + "description": "", + "i18n_label_key": "admin_settings_field_log_payments_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_SUPPORT", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать тикеты поддержки", + "description": "", + "i18n_label_key": "admin_settings_field_log_support_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_PROMO_ACTIVATIONS", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать активации промокодов", + "description": "", + "i18n_label_key": "admin_settings_field_log_promo_activations_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_TRIAL_ACTIVATIONS", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать активации триала", + "description": "", + "i18n_label_key": "admin_settings_field_log_trial_activations_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_SUSPICIOUS_ACTIVITY", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать подозрительные действия", + "description": "", + "i18n_label_key": "admin_settings_field_log_suspicious_activity_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_ADMIN_ACTIONS", + "type": "bool", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Логировать действия администраторов", + "description": "Если выключено, события от пользователей из ADMIN_IDS не записываются в message logs.", + "i18n_label_key": "admin_settings_field_log_admin_actions_label", + "i18n_description_key": "admin_settings_field_log_admin_actions_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_LEVEL", + "type": "string", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "Глобальный уровень логов", + "description": "DEBUG / INFO / WARNING / ERROR", + "i18n_label_key": "admin_settings_field_log_level_label", + "i18n_description_key": "admin_settings_field_log_level_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_CHAT_ID", + "type": "int", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "ID чата для логов", + "description": "", + "i18n_label_key": "admin_settings_field_log_chat_id_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_THREAD_ID", + "type": "int", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "ID треда (для супергрупп)", + "description": "", + "i18n_label_key": "admin_settings_field_log_thread_id_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "LOG_SUPPORT_THREAD_ID", + "type": "int", + "section": "notifications", + "section_order": 7, + "subsection": null, + "label": "ID треда поддержки", + "description": "Тред лог-чата для уведомлений о тикетах поддержки.", + "i18n_label_key": "admin_settings_field_log_support_thread_id_label", + "i18n_description_key": "admin_settings_field_log_support_thread_id_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "support", + "order": 8, + "fields": [ + { + "key": "SUPPORT_TICKETS_ENABLED", + "type": "bool", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Тикеты поддержки включены", + "description": "Показывает раздел поддержки в ЛК и включает создание тикетов.", + "i18n_label_key": "admin_settings_field_support_tickets_enabled_label", + "i18n_description_key": "admin_settings_field_support_tickets_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_ADMIN_EMAIL_NOTIFICATIONS_ENABLED", + "type": "bool", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Email-уведомления админам", + "description": "Если выключено, новые тикеты и ответы пользователей останутся только в Telegram и лог-чате.", + "i18n_label_key": "admin_settings_field_support_admin_email_notifications_enabled_label", + "i18n_description_key": "admin_settings_field_support_admin_email_notifications_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_ADMIN_NOTIFICATION_COOLDOWN_SECONDS", + "type": "int", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Пауза Telegram-уведомлений", + "description": "Минимум секунд между повторными Telegram/log уведомлениями по одному непрочитанному тикету.", + "i18n_label_key": "admin_settings_field_support_admin_notification_cooldown_seconds_label", + "i18n_description_key": "admin_settings_field_support_admin_notification_cooldown_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_ADMIN_EMAIL_COOLDOWN_SECONDS", + "type": "int", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Пауза email-уведомлений", + "description": "Минимум секунд между повторными email-уведомлениями по одному непрочитанному тикету.", + "i18n_label_key": "admin_settings_field_support_admin_email_cooldown_seconds_label", + "i18n_description_key": "admin_settings_field_support_admin_email_cooldown_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_TICKET_MAX_BODY_LENGTH", + "type": "int", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Макс. длина сообщения", + "description": "Максимальное количество символов в сообщении тикета.", + "i18n_label_key": "admin_settings_field_support_ticket_max_body_length_label", + "i18n_description_key": "admin_settings_field_support_ticket_max_body_length_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_TICKET_MAX_SUBJECT_LENGTH", + "type": "int", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Макс. длина темы", + "description": "Максимальное количество символов в теме тикета.", + "i18n_label_key": "admin_settings_field_support_ticket_max_subject_length_label", + "i18n_description_key": "admin_settings_field_support_ticket_max_subject_length_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUPPORT_TICKET_RATE_LIMIT_PER_HOUR", + "type": "int", + "section": "support", + "section_order": 8, + "subsection": null, + "label": "Лимит тикетов в час", + "description": "Сколько новых тикетов пользователь может создать за час. 0 — без лимита.", + "i18n_label_key": "admin_settings_field_support_ticket_rate_limit_per_hour_label", + "i18n_description_key": "admin_settings_field_support_ticket_rate_limit_per_hour_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "backups", + "order": 9, + "fields": [ + { + "key": "BACKUP_ENABLED", + "type": "bool", + "section": "backups", + "section_order": 9, + "subsection": null, + "label": "Бэкапы включены", + "description": "Worker будет периодически собирать ZIP-архив и отправлять его в Telegram.", + "i18n_label_key": "admin_settings_field_backup_enabled_label", + "i18n_description_key": "admin_settings_field_backup_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "BACKUP_CHAT_ID", + "type": "int", + "section": "backups", + "section_order": 9, + "subsection": null, + "label": "ID чата для бэкапов", + "description": "Куда отправлять ZIP-архивы. Если пусто, используется LOG_CHAT_ID.", + "i18n_label_key": "admin_settings_field_backup_chat_id_label", + "i18n_description_key": "admin_settings_field_backup_chat_id_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "BACKUP_THREAD_ID", + "type": "int", + "section": "backups", + "section_order": 9, + "subsection": null, + "label": "ID треда для бэкапов", + "description": "Необязательный topic/thread ID. Если пусто, используется LOG_THREAD_ID.", + "i18n_label_key": "admin_settings_field_backup_thread_id_label", + "i18n_description_key": "admin_settings_field_backup_thread_id_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "BACKUP_INTERVAL_SECONDS", + "type": "int", + "section": "backups", + "section_order": 9, + "subsection": null, + "label": "Период бэкапов (сек.)", + "description": "По умолчанию 3600: запуск на границе часа (12:00, 13:00 и т.д.).", + "i18n_label_key": "admin_settings_field_backup_interval_seconds_label", + "i18n_description_key": "admin_settings_field_backup_interval_seconds_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 60, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "BACKUP_LOCAL_RETENTION", + "type": "int", + "section": "backups", + "section_order": 9, + "subsection": null, + "label": "Сколько архивов хранить", + "description": "Сколько последних ZIP-архивов оставлять в data/backups на сервере.", + "i18n_label_key": "admin_settings_field_backup_local_retention_label", + "i18n_description_key": "admin_settings_field_backup_local_retention_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 1, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "BACKUP_COMPOSE_ENABLED", + "type": "bool", + "section": "backups", + "section_order": 9, + "subsection": null, + "label": "Добавлять compose-папку", + "description": "Добавляет snapshot /app/compose-source. Если папка не смонтирована, бэкап БД все равно будет создан.", + "i18n_label_key": "admin_settings_field_backup_compose_enabled_label", + "i18n_description_key": "admin_settings_field_backup_compose_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "subscription_guides", + "order": 10, + "fields": [ + { + "key": "SUBSCRIPTION_GUIDES_ENABLED", + "type": "bool", + "section": "subscription_guides", + "section_order": 10, + "subsection": null, + "label": "Embedded install guides", + "description": "Open install instructions inside the Web App instead of an external connect page.", + "i18n_label_key": "admin_settings_field_subscription_guides_enabled_label", + "i18n_description_key": "admin_settings_field_subscription_guides_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_GUIDES_BOT_MENU_ENABLED", + "type": "bool", + "section": "subscription_guides", + "section_order": 10, + "subsection": null, + "label": "Open install guides from bot", + "description": "Use the Telegram Mini App install screen for bot connect buttons and show public install guide links.", + "i18n_label_key": "admin_settings_field_subscription_guides_bot_menu_enabled_label", + "i18n_description_key": "admin_settings_field_subscription_guides_bot_menu_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_PAGE_CONFIG_PANEL_ENABLED", + "type": "bool", + "section": "subscription_guides", + "section_order": 10, + "subsection": null, + "label": "Use Remnawave Panel config", + "description": "Fetch Subscription Page config from Remnawave Panel by the user's subscription short UUID.", + "i18n_label_key": "admin_settings_field_subscription_page_config_panel_enabled_label", + "i18n_description_key": "admin_settings_field_subscription_page_config_panel_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_PAGE_CONFIG_JSON_OVERRIDE_ENABLED", + "type": "bool", + "section": "subscription_guides", + "section_order": 10, + "subsection": null, + "label": "Enable admin JSON override", + "description": "Use the JSON field below instead of Remnawave Panel config. Disabled by default.", + "i18n_label_key": "admin_settings_field_subscription_page_config_json_override_enabled_label", + "i18n_description_key": "admin_settings_field_subscription_page_config_json_override_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_PAGE_CONFIG_PATH", + "type": "string", + "section": "subscription_guides", + "section_order": 10, + "subsection": null, + "label": "Subscription Page config path", + "description": "Fallback path to a Remnawave Subscription Page v1 JSON config file.", + "i18n_label_key": "admin_settings_field_subscription_page_config_path_label", + "i18n_description_key": "admin_settings_field_subscription_page_config_path_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": "admin_settings_field_subscription_page_config_path_placeholder", + "placeholder": "data/subpage-config/multiapp.json", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "SUBSCRIPTION_PAGE_CONFIG_JSON", + "type": "json", + "section": "subscription_guides", + "section_order": 10, + "subsection": null, + "label": "Subscription Page config JSON", + "description": "Optional admin JSON override. It is applied only when the JSON override switch is enabled.", + "i18n_label_key": "admin_settings_field_subscription_page_config_json_label", + "i18n_description_key": "admin_settings_field_subscription_page_config_json_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": "admin_settings_field_subscription_page_config_json_placeholder", + "placeholder": "{\n \"version\": \"1\"\n}", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "devices", + "order": 10, + "fields": [ + { + "key": "MY_DEVICES_SECTION_ENABLED", + "type": "bool", + "section": "devices", + "section_order": 10, + "subsection": null, + "label": "Раздел «Мои устройства»", + "description": "", + "i18n_label_key": "admin_settings_field_my_devices_section_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "USER_HWID_DEVICE_LIMIT", + "type": "int", + "section": "devices", + "section_order": 10, + "subsection": null, + "label": "Лимит устройств по умолчанию (0 = ∞)", + "description": "", + "i18n_label_key": "admin_settings_field_user_hwid_device_limit_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "USER_TRAFFIC_LIMIT_GB", + "type": "float", + "section": "devices", + "section_order": 10, + "subsection": null, + "label": "Лимит трафика пользователя (ГБ)", + "description": "", + "i18n_label_key": "admin_settings_field_user_traffic_limit_gb_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "USER_TRAFFIC_STRATEGY", + "type": "string", + "section": "devices", + "section_order": 10, + "subsection": null, + "label": "Стратегия сброса трафика", + "description": "", + "i18n_label_key": "admin_settings_field_user_traffic_strategy_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "pricing", + "order": 11, + "fields": [ + { + "key": "MONTH_1_ENABLED", + "type": "bool", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Тариф 1 месяц", + "description": "", + "i18n_label_key": "admin_settings_field_month_1_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "MONTH_3_ENABLED", + "type": "bool", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Тариф 3 месяца", + "description": "", + "i18n_label_key": "admin_settings_field_month_3_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "MONTH_6_ENABLED", + "type": "bool", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Тариф 6 месяцев", + "description": "", + "i18n_label_key": "admin_settings_field_month_6_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "MONTH_12_ENABLED", + "type": "bool", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Тариф 12 месяцев", + "description": "", + "i18n_label_key": "admin_settings_field_month_12_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "RUB_PRICE_1_MONTH", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 1 мес. (RUB)", + "description": "", + "i18n_label_key": "admin_settings_field_rub_price_1_month_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "RUB_PRICE_3_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 3 мес. (RUB)", + "description": "", + "i18n_label_key": "admin_settings_field_rub_price_3_months_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "RUB_PRICE_6_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 6 мес. (RUB)", + "description": "", + "i18n_label_key": "admin_settings_field_rub_price_6_months_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "RUB_PRICE_12_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 12 мес. (RUB)", + "description": "", + "i18n_label_key": "admin_settings_field_rub_price_12_months_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_PRICE_1_MONTH", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 1 мес. (Stars)", + "description": "", + "i18n_label_key": "admin_settings_field_stars_price_1_month_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_PRICE_3_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 3 мес. (Stars)", + "description": "", + "i18n_label_key": "admin_settings_field_stars_price_3_months_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_PRICE_6_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 6 мес. (Stars)", + "description": "", + "i18n_label_key": "admin_settings_field_stars_price_6_months_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_PRICE_12_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Цена 12 мес. (Stars)", + "description": "", + "i18n_label_key": "admin_settings_field_stars_price_12_months_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_INVITER_1_MONTH", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашающему: 1 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_inviter_1_month_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_INVITER_3_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашающему: 3 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_inviter_3_months_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_INVITER_6_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашающему: 6 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_inviter_6_months_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_INVITER_12_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашающему: 12 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_inviter_12_months_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_REFEREE_1_MONTH", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашённому: 1 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_referee_1_month_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_REFEREE_3_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашённому: 3 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_referee_3_months_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_REFEREE_6_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашённому: 6 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_referee_6_months_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "REFERRAL_BONUS_DAYS_REFEREE_12_MONTHS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "legacy_tariffs", + "label": "Бонус приглашённому: 12 мес.", + "description": "", + "i18n_label_key": "admin_settings_field_referral_bonus_days_referee_12_months_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_legacy_tariffs", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TRAFFIC_PACKAGES", + "type": "string", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Пакеты трафика", + "description": "Формат: 10:199,50:799 (ГБ:цена)", + "i18n_label_key": "admin_settings_field_traffic_packages_label", + "i18n_description_key": "admin_settings_field_traffic_packages_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "STARS_TRAFFIC_PACKAGES", + "type": "string", + "section": "pricing", + "section_order": 11, + "subsection": null, + "label": "Пакеты трафика (Stars)", + "description": "", + "i18n_label_key": "admin_settings_field_stars_traffic_packages_label", + "i18n_description_key": null, + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TRIAL_ENABLED", + "type": "bool", + "section": "pricing", + "section_order": 11, + "subsection": "trial", + "label": "Триал включён", + "description": "", + "i18n_label_key": "admin_settings_field_trial_enabled_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_trial", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TRIAL_DURATION_DAYS", + "type": "int", + "section": "pricing", + "section_order": 11, + "subsection": "trial", + "label": "Длительность триала (дней)", + "description": "", + "i18n_label_key": "admin_settings_field_trial_duration_days_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_trial", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TRIAL_TRAFFIC_LIMIT_GB", + "type": "float", + "section": "pricing", + "section_order": 11, + "subsection": "trial", + "label": "Лимит трафика триала (ГБ)", + "description": "", + "i18n_label_key": "admin_settings_field_trial_traffic_limit_gb_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_trial", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "min": 0, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TRIAL_TRAFFIC_STRATEGY", + "type": "string", + "section": "pricing", + "section_order": 11, + "subsection": "trial", + "label": "Стратегия сброса трафика триала", + "description": "", + "i18n_label_key": "admin_settings_field_trial_traffic_strategy_label", + "i18n_description_key": null, + "i18n_subsection_key": "admin_settings_subsection_trial", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": false, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "TRIAL_SQUAD_UUIDS", + "type": "string", + "section": "pricing", + "section_order": 11, + "subsection": "trial", + "label": "Internal Squads для триала", + "description": "UUID через запятую. Если пусто, используется USER_SQUAD_UUIDS.", + "i18n_label_key": "admin_settings_field_trial_squad_uuids_label", + "i18n_description_key": "admin_settings_field_trial_squad_uuids_description", + "i18n_subsection_key": "admin_settings_subsection_trial", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "system", + "order": 12, + "fields": [ + { + "key": "TELEMETRY_ENABLED", + "type": "bool", + "section": "system", + "section_order": 12, + "subsection": null, + "label": "Анонимная статистика установки", + "description": "Раз в сутки отправляет обезличенный сигнал: версия, ОС, локаль и число пользователей в виде диапазона. Без персональных данных, токенов и доменов. Помогает понять число активных установок и какие версии используются. Можно отключить здесь без перезапуска.", + "i18n_label_key": "admin_settings_field_telemetry_enabled_label", + "i18n_description_key": "admin_settings_field_telemetry_enabled_description", + "i18n_subsection_key": null, + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + }, + { + "id": "migrations", + "order": 13, + "fields": [ + { + "key": "MIGRATION_REMNASHOP_REFERRAL_CODE_COMPAT_ENABLED", + "type": "bool", + "section": "migrations", + "section_order": 13, + "subsection": "Remnashop", + "label": "Старые ref-ссылки Remnashop", + "description": "Принимать импортированные ref-коды Remnashop вместе с текущими кодами пользователей.", + "i18n_label_key": "admin_settings_field_migration_remnashop_referral_code_compat_enabled_label", + "i18n_description_key": "admin_settings_field_migration_remnashop_referral_code_compat_enabled_description", + "i18n_subsection_key": "admin_settings_subsection_remnashop", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "MIGRATION_REMNASHOP_PROMO_CODE_COMPAT_ENABLED", + "type": "bool", + "section": "migrations", + "section_order": 13, + "subsection": "Remnashop", + "label": "Старые промокоды Remnashop", + "description": "Пробовать точное совпадение промокода перед обычной uppercase-нормализацией.", + "i18n_label_key": "admin_settings_field_migration_remnashop_promo_code_compat_enabled_label", + "i18n_description_key": "admin_settings_field_migration_remnashop_promo_code_compat_enabled_description", + "i18n_subsection_key": "admin_settings_subsection_remnashop", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "MIGRATION_REMNASHOP_IMPORTED_AT", + "type": "string", + "section": "migrations", + "section_order": 13, + "subsection": "Remnashop", + "label": "Последний импорт Remnashop", + "description": "Заполняется скриптом импорта. Можно очистить, если отметка больше не нужна.", + "i18n_label_key": "admin_settings_field_migration_remnashop_imported_at_label", + "i18n_description_key": "admin_settings_field_migration_remnashop_imported_at_description", + "i18n_subsection_key": "admin_settings_subsection_remnashop", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + }, + { + "key": "MIGRATION_REMNASHOP_NOTES", + "type": "text", + "section": "migrations", + "section_order": 13, + "subsection": "Remnashop", + "label": "Заметки по миграции Remnashop", + "description": "Внутренние заметки оператора по перенесенному инстансу.", + "i18n_label_key": "admin_settings_field_migration_remnashop_notes_label", + "i18n_description_key": "admin_settings_field_migration_remnashop_notes_description", + "i18n_subsection_key": "admin_settings_subsection_remnashop", + "i18n_placeholder_key": null, + "placeholder": "", + "optional": true, + "secret": false, + "value": "", + "overridden": false, + "updated_at": null + } + ] + } +] diff --git a/scripts/export_settings_manifest.py b/scripts/export_settings_manifest.py new file mode 100644 index 0000000..ea4b389 --- /dev/null +++ b/scripts/export_settings_manifest.py @@ -0,0 +1,96 @@ +"""Export the admin settings manifest as a demo-safe JSON snapshot. + +The Mini App demo (docs site) has no backend, so its admin Settings screen is +fed by a mock. Previously the section/field structure was frozen inside the +externally-generated ``demoDataset.js`` snapshot, which drifted from the real +manifest (e.g. the Remnawave Panel section was missing). + +This script regenerates ``frontend/src/lib/webapp/settingsManifest.generated.json`` +straight from :func:`manifest_payload` — the same source of truth the live +``/admin/settings`` endpoint uses — grouped into sections exactly like +``admin_settings_get_route``. The demo overlays its realistic values on top of +this structure, so adding a field in Python is enough to keep the demo in sync. + +Usage:: + + python scripts/export_settings_manifest.py + +A pytest drift guard (``tests/test_settings_manifest_demo_sync.py``) compares the +committed JSON against a fresh build, so the snapshot cannot silently drift. +After regenerating, run Prettier so the file matches the frontend code style:: + + npx --prefix frontend prettier --write src/lib/webapp/settingsManifest.generated.json +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path +from typing import Any, Dict, List + +ROOT = Path(__file__).resolve().parents[1] +BACKEND = ROOT / "backend" +for _path in (str(BACKEND), str(ROOT)): + if _path not in sys.path: + sys.path.insert(0, _path) + +from bot.app.web.admin_settings_manifest import manifest_payload # noqa: E402 + +OUTPUT_PATH = ROOT / "frontend" / "src" / "lib" / "webapp" / "settingsManifest.generated.json" + + +def build_demo_settings_sections() -> List[Dict[str, Any]]: + """Group the manifest into ordered sections with demo-safe field values. + + Mirrors :func:`bot.app.web.admin_api_impl.settings.admin_settings_get_route` + but without any database- or settings-derived values: every field starts + empty/unoverridden and secrets expose no value. The demo fills in realistic + values per field key at runtime. + """ + fields = manifest_payload() + sections: Dict[str, Dict[str, Any]] = {} + for field in fields: + section_id = field["section"] + if section_id not in sections: + sections[section_id] = { + "id": section_id, + "order": field["section_order"], + "fields": [], + } + is_secret = bool(field.get("secret")) + response_field: Dict[str, Any] = { + **field, + "value": "", + "overridden": False, + "updated_at": None, + } + if is_secret: + response_field["has_value"] = False + webhook_path = str(response_field.get("webhook_path") or "").strip() + if webhook_path: + if not webhook_path.startswith("/"): + webhook_path = f"/{webhook_path}" + response_field["webhook_path"] = webhook_path + response_field["webhook_base_url_configured"] = False + sections[section_id]["fields"].append(response_field) + + return sorted(sections.values(), key=lambda section: section["order"]) + + +def render_json(sections: List[Dict[str, Any]]) -> str: + return json.dumps(sections, ensure_ascii=False, indent=2) + "\n" + + +def main() -> int: + sections = build_demo_settings_sections() + OUTPUT_PATH.write_text(render_json(sections), encoding="utf-8") + field_count = sum(len(section["fields"]) for section in sections) + print( + f"Wrote {len(sections)} sections / {field_count} fields to {OUTPUT_PATH.relative_to(ROOT)}" + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_settings_manifest_demo_sync.py b/tests/test_settings_manifest_demo_sync.py new file mode 100644 index 0000000..412b37a --- /dev/null +++ b/tests/test_settings_manifest_demo_sync.py @@ -0,0 +1,51 @@ +"""Guard that the demo settings manifest snapshot stays in sync with Python. + +The Mini App demo feeds its admin Settings screen from +``frontend/src/lib/webapp/settingsManifest.generated.json``, generated off the +real :func:`manifest_payload`. If a developer adds or changes a settings field +in Python without regenerating that snapshot, this test fails and tells them how +to refresh it — keeping the demo automatically in step with reality. +""" + +from __future__ import annotations + +import importlib.util +import json +import unittest +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[1] +_GENERATOR_PATH = _REPO_ROOT / "scripts" / "export_settings_manifest.py" + +_spec = importlib.util.spec_from_file_location("export_settings_manifest", _GENERATOR_PATH) +export_settings_manifest = importlib.util.module_from_spec(_spec) +_spec.loader.exec_module(export_settings_manifest) + +OUTPUT_PATH = export_settings_manifest.OUTPUT_PATH +build_demo_settings_sections = export_settings_manifest.build_demo_settings_sections + + +class SettingsManifestDemoSyncTests(unittest.TestCase): + def test_committed_snapshot_matches_manifest(self): + self.assertTrue( + OUTPUT_PATH.exists(), + "Generated settings manifest snapshot is missing; run " + "`python scripts/export_settings_manifest.py`.", + ) + committed = json.loads(OUTPUT_PATH.read_text(encoding="utf-8")) + expected = build_demo_settings_sections() + self.assertEqual( + committed, + expected, + "Demo settings manifest is stale. Regenerate it with " + "`python scripts/export_settings_manifest.py` and re-run Prettier.", + ) + + def test_snapshot_includes_remnawave_section(self): + committed = json.loads(OUTPUT_PATH.read_text(encoding="utf-8")) + section_ids = {section["id"] for section in committed} + self.assertIn("remnawave", section_ids) + + +if __name__ == "__main__": + unittest.main()