# Системные настройки — Администрирование

Системные настройки — общая административная часть платформы: глобальные параметры приложения, подключение интеграционных сервисов, управление модулями и фоновыми задачами (джобами). Раздел описывает, где задаются эти настройки, какие параметры критичны для стабильной работы, справочник ключей `appsettings.json` и типичные ошибки конфигурации. Адресован администраторам площадки и инженерам поддержки.

## Обзор

Домен system — кросс-доменный административный контур, включающий глобальные настройки приложения, сервисы интеграций, модули, управление фоновыми задачами и инфраструктурные провайдеры. Администрирование использует:

- **Автоадминка (dbadmin)** — 24+ форм (system-settings 363 поля/22 секции, пользовательскые настройки, модули, локализация, 17+ форм интеграционных сервисов)
- **EntityEditor** — схемы `authenticationProviders`, `domains`, `fileProviderDefault`, `includes`, `licenses`, `licensesList`, `shortlinks`
- **Admin API** — 6+ контроллеров (модули, сервисы, jobs, LDAP, auth-провайдеры, файловые провайдеры, includes)

## Механизмы администрирования

### Автоадминка (dbadmin) — основные формы

Основные формы администрирования, доступные через `AdminSPA → Режим администрирования → автоадминка`.

**Поставка метакаталога.** Описание форм (`dbadmin.AdminForms`, `AdminFormSections`, `AdminFormSectionColumns`, `AdminFormSectionColumnsDeps`, `AdminFormFolders`, `DbaColumns`, `DbaObjects`) поставляется миграциями и накатывается полным пересидом: миграция удаляет содержимое этих таблиц целиком и вставляет заново. Следствие — ручные правки метакаталога прямо в БД теряются при накате следующей версии; изменения формы вносятся в исходник миграции, а не в таблицу.

**Идентификаторы элементов метакаталога.** Номера элементов метакаталога (`DbaColumns.Id`, `AdminFormSections.Id`, `AdminFormSectionColumns.Id`) назначаются по-разному в зависимости от того, как метакаталог поставляется. Точечная миграция — та, что добавляет один элемент к уже поставленному метакаталогу, — номера вручную не прописывает: номер берётся у таблицы, а все ссылки на новый элемент строятся по возвращённому номеру. Полный снимок метакаталога, наоборот, пересобирает таблицы целиком и вставляет строки с явными номерами: там номера — часть снимка, и повторять их в других миграциях нельзя.

Два следствия для PostgreSQL. Первое: снимок чистит таблицы и переливает строки с явными номерами, но последовательности не трогает, поэтому после него обязателен отдельный шаг выравнивания последовательностей — иначе следующая вставка через последовательность упадёт с повтором первичного ключа. Для MS SQL шаг не нужен: вставка с явно заданным значением поднимает счётчик сама. Второе: если накат упал с повтором первичного ключа по таблице метакаталога, значит номер уже занят другим элементом, и выравнивание последовательностей проблему не решит. На стенде снимают метаданные элемента, который занял номер, и перезапускают накат — полный снимок восстановит нужное состояние. Перенести номер вручную (`update … set id`) не получится: мешает внешний ключ от колонок секции, а копия строки под новым номером падает на уникальности пары «объект и подпись».

**Точечные правки пунктов меню.** Отдельные атрибуты формы — например адрес `Url`, по которому из левого меню открывается страница AdminSPA, — меняются адресной миграцией, без полного выгруза и пересида таблицы. Миграция должна быть парной: скрипт `.sql` для MSSQL и скрипт `.pgsql` для PostgreSQL с совпадающим идентификатором. Пример из сборки 2.268: форме `sms-providers` (Id 76) задаётся `Url = '/administration/sms-providers'`, а в форме 71 «Общие настройки приложения» той же миграцией заменяется адрес действия «Сервис отправки СМС».

| Alias формы | Название | Таблица БД | Полей | Секций | Deps | Папка |
|-------------|----------|-----------|-------|--------|------|-------|
| `system-settings` ¹ | Общие настройки приложения | dbo.Settings | 363 | 22 | 7 | Системные настройки |
| `custom-settings` | Пользовательскые настройки приложения | dbo.SettingsCustom | 6 | 1 | 0 | Системные настройки |
| `modules` ³ | Модули | dbo.Modules | 3 | 1 | 0 | Дополнительно |
| `localization-resources` | Ресурсы локализации | dbo.LocalizationResources | 5 | 1 | 0 | Устаревшее |
| `equivalent-chars` | Равнозначные буквы | dbo.EquivalentChars | 4 | 1 | 0 | Служебное |
| `system-services` ² | Сервисы | dbo.ServicesSettings | 5 | 1 | 0 | Подключения |

¹ Форма `system-settings` использует автоадминку в **режиме edit** (Url = `/admin-ds/forms/system-settings/edit?column=[SettingID]&value=1`). Таблица `dbo.Settings` содержит единственную строку, поэтому грид не нужен — клик ведёт сразу в форму редактирования.

² В AdminSPA форма `system-services` реализована как пользовательская форма с динамическим составом полей в зависимости от типа сервиса. См. [admin-ui/business.md](https://help.1forma.ru/domains/admin-ui/business.md), сценарий 4.

³ В AdminSPA список модулей доступен отдельной страницей «Модули» (`/administration/modules`) — только на чтение: название модуля и «ID версии конфигурации» (если не заполнен — «не задана»), при отсутствии модулей выводится «Список модулей пуст». Создание, изменение и удаление модулей — через форму автоадминки или Admin API. Кнопки создания и удаления страница показывает по правам текущего пользователя: без полных административных прав они скрыты. При удалении модуль со связанными сущностями не удаляется — интерфейс получает перечень того, что мешает, с количеством записей по каждому типу.

#### Роли модуля

Из карточки модуля доступен переход к ролям бизнес-процесса этого модуля. Экран показывает роли только выбранного модуля: идентификатор роли, отображаемое название, описание и категории модуля, в которых роль используется. Фильтр по модулю берётся из адреса страницы, поэтому переход к ролям другого модуля показывает роли этого модуля, а не все роли площадки.

Клик по строке открывает карточку роли по отдельному адресу с идентификаторами модуля и роли. Доступ к экрану — только у пользователя с полными административными правами. Если роль не принадлежит указанному модулю, карточка сообщает, что роль не найдена: ни сохранить, ни удалить привязку в ней нельзя.

В карточке — название и описание роли и блок «Использование роли»: группы — категории модуля, строки — статусы и переходы этих категорий. Название обязательно: пустое значение и строка из одних пробелов не сохраняются, кнопка «Сохранить» при этом недоступна. Описание необязательно. Пока сохранение не завершилось, повторное нажатие не отправляет второй запрос; после сохранения карточка перечитывается.

Корзинка в строке удаляет одну привязку роли к переходу — ровно пару «роль и переход». Сама роль и её подписи при этом не удаляются. Если у категории больше не осталось привязок, группа с этой категорией исчезает из карточки. Создание новой роли на этом экране не выполняется: роль создаётся в модуле категории.

### Автоадминка (dbadmin) — интеграционные сервисы

Формы настройки внешних интеграций: аутентификационные провайдеры, почтовые сервисы, Diadoc, СБИС и другие.

| Alias формы | Название | Таблица БД | Полей | Папка |
|-------------|----------|-----------|-------|-------|
| `authentication-providers` | Провайдеры аутентификации | dbo.AuthenticationProviders | 13 | Подключения |
| `active-directory-service-settings` | Сервис Active Directory | dbo.LDAPServicesCredentials | 7 | Подключения |
| `openldap-service-settings` | Сервис OpenLDAP | dbo.OpenLDAPServicesCredentials | 8 | Подключения |
| `oauth-service-settings` | Сервис OAuth | dbo.OAuthServicesSettings | 9 | Подключения |
| `saml-service-settings` | Сервис SAML | dbo.SAMLServicesSettings | 6 | Подключения |
| `radius-service-settings` | Сервис Radius | dbo.RadiusServicesCredentials | 6 | Подключения |
| `multifactor-service-settings` | Сервис Multifactor | dbo.MultifactorCredentials | 6 | Подключения |
| `ews-service-settings` | Сервис ExchangeWebService | dbo.EwsServiceSettings | 12 | Подключения |
| `diadoc-service-settings` | Сервис Diadoc | dbo.DiadocServiceCredentials | 8 | Подключения |
| `sbis-service-settings` | Сервис Sbis | dbo.SbisCredentials | 9 | Подключения |
| `dadata-service-settings` | Сервис Dadata | dbo.DadataServiceCredentials | 5 | Подключения |
| `paycontrol-service-settings` | Сервис PayControl | dbo.PayControlServiceCredentials | 10 | Подключения |
| `tika-service-settings` | Сервис Tika | dbo.TikaServiceSettings | 8 | Подключения |
| `azure-service-settings` | Сервис TranslateService | dbo.AzureCognitiveServiceCredentials | 8 | Подключения |
| `universalapi-service-settings` | Сервис UniversalApi | dbo.UniversalApiServiceSettings | 7 | Подключения |
| `vector-search-service-settings` | Сервис VectorSearch | dbo.VectorSearchServiceSettings | 4 | Подключения |

### EntityEditor

EntityEditor предоставляет JSON-схемы для расширенного редактирования сущностей, недоступных в стандартных формах автоадминки.

| Схема JSON | Таблица | Назначение |
|-----------|---------|------------|
| `authenticationProviders` | dbo.AuthenticationProviders | Расширенная настройка auth-провайдеров |
| `domains` | dbo.Domains | Домены организации |
| `fileProviderDefault` | (виртуальная) | Провайдер по умолчанию |
| `includes` | dbo.Includes | Глобальные JS/CSS includes |
| `licenses` | dbo.Licenses | Управление лицензиями |
| `licensesList` | (связанная) | Список лицензий |
| `shortlinks` | dbo.ShortLinks | Короткие ссылки |

**Провайдеры СМС.** Настройка СМС-провайдеров ведётся не через EntityEditor и не общей формой автоадминки, а отдельной страницей администрирования — её состав описан в разделе «Провайдеры СМС» ниже. Пункт меню «Провайдеры СМС» и старые адреса `smsProviderSettings` и `smsProviderSettings/1` ведут на эту страницу; технический вид таблицы сохранён в форме автоадминки `sms-providers` (`/admin-ds/forms/sms-providers/grid`, таблица `dbo.SMSProviders`, папка «Дополнительно») и открывается только по прямому адресу.

**Как строится пункт меню.** Пункт «Провайдеры СМС» панели администрирования берёт адрес не из формы, а из колонки `Url` записи формы `sms-providers` (Id 76) в `dbadmin.AdminForms`; там задано `/administration/sms-providers`, поэтому клик по пункту открывает страницу AdminSPA, а не грид автоадминки. Если `Url` пуст, панель открывает грид формы по адресу `/admin-ds/forms/{alias}/grid` — так продолжают работать остальные пункты дерева. Адрес меняется адресной миграцией в ядре, а не из интерфейса: `update dbadmin.AdminForms set Url = '/administration/sms-providers' where Id = 76 and Alias = 'sms-providers'`. Той же миграцией в форме 71 «Общие настройки приложения» заменяется адрес действия «Сервис отправки СМС» — подстрокой `/administration/entity/smsProviderSettings/1` в колонке `RowActions`, чтобы не затронуть остальные действия формы. Форма 208 этой миграцией не затрагивается и остаётся на прежнем адресе. Задача формы 76 при этом сохранена: таблица `dbo.SMSProviders` и технический вид по адресу `/admin-ds/forms/sms-providers/grid` остаются рабочими — `Url` влияет только на переход из меню.

Обработчик автоадминки `SmsProvidersUpdateHandler` привязан к объекту `dbo.SMSProviders`: при чтении раскладывает XML-колонку `Settings` на отдельные поля (логин, пароль, отправители, прокси, SMTP, адрес сервиса, API-ключи, метод HTTP), при записи собирает их обратно в XML, читая актуальное значение из БД, — частичное обновление не затирает нетронутые элементы. Удаление провайдеров запрещено (`AllowDeleteF = 0` на форме плюс проверка в обработчике).

**Секреты провайдера.** Пароль, пароль прокси, идентификатор API, ключ и секрет API хранятся в `Settings` зашифрованными. В карточке провайдера и в форме автоадминки заполненный секрет показывается заглушкой `********` — прочитать или скопировать сохранённое значение через интерфейс нельзя; незаполненный остаётся пустым, а сырая колонка `Settings` в ответе формы обнуляется.

| Что в поле при сохранении | Что происходит |
|---|---|
| Заглушка `********` | Секрет не меняется |
| Пусто | Секрет очищается |
| Новое значение | Значение шифруется и сохраняется |

Секреты, сохранённые в открытом виде раньше, читаются при отправке SMS наравне с зашифрованными и перешифровываются при очередном сохранении карточки этого провайдера — отдельной массовой перешифровки нет.

Страницу обслуживает `SmsProvidersAdminController` (`/api/admin/sms-providers`): `GET` списка провайдеров с отметкой «по умолчанию», `GET {id}` карточки одного провайдера с разобранными настройками (секреты замаскированы, сырой XML и расшифрованные значения наружу не уходят), `GET classes` — справочник классов провайдеров с перечнем полей каждого (15 классов), `POST` создание и `POST {id}` сохранение провайдера, `POST set-default` — назначение провайдера по умолчанию (`Settings.SMSProviderID`), `POST test-send` — тестовая отправка через указанного провайдера (при переданных настройках они предварительно сохраняются). Все методы требуют прав суперадминистратора. Ошибки проверки возвращают код 400 с текстом причины: имя обязательно, класс должен существовать, смена класса запрещена, собранный XML настроек не длиннее 2000 символов, при сохранении меняются только переданные значения; `set-default` проверяет, что провайдер существует. После создания и сохранения провайдера, а также после смены провайдера по умолчанию сбрасывается кеш провайдера по умолчанию, поэтому изменение действует без перезапуска.

### Admin API контроллеры

Admin API доступен только пользователям с административными правами. Все маршруты находятся в пространстве `/api/admin/`.

| Контроллер | Маршрут | Методы | Назначение |
|-----------|---------|--------|------------|
| ModulesController | `/api/admin/modules` | GET, POST, PUT, DELETE | CRUD модулей (требует прав суперадминистратора). С 2.268.342 появились маршруты записи (`POST`/`PUT`/`DELETE`) — до этого был только `GET` списка, запись шла через форму автоадминки 265. Форма 265 сохранена для совместимости. На `DELETE` сервис проверяет 13 FK-зависимостей (`Subcategories`, `Categories`, `ExtParams`, `ActionsPacks`, `SmartExpressions`, `SmartScripts`, `Signatures`, `States`, `PortalGridBlocks`, `PortalGridTemplates`, `Reports`, `BpRoles`, `VersionConfigs`); при наличии ссылок удаление блокируется. |
| ServicesAdminController | `/api/admin/services` | GET, POST | Состояние и управление сервисами |
| JobsAdminController | `/api/admin/jobs` | GET, POST | Управление фоновыми задачами |
| LdapController | `/api/admin/ldap` (`providers`, `search-users`, `search-groups`) | GET, POST | Поиск пользователей и групп в каталоге, список активных профилей AD-синхронизации. **В 1F Certificate Edition (ФСТЭК-сборка `UniForm.Barebone`) контроллер не входит в сборку: маршруты отсутствуют, ответ 404** |
| AuthProvidersController | `/api/admin/authentication-providers` | GET, POST, DELETE | CRUD auth-провайдеров |
| FileProvidersController | `/api/admin/fileproviders` | GET, POST, PUT | Файловые провайдеры |
| SmsProvidersAdminController | `/api/admin/sms-providers` | GET, POST | СМС-провайдеры: список, карточка с разобранными настройками, справочник классов, создание, сохранение, провайдер по умолчанию, тестовая отправка. Все методы требуют прав суперадминистратора. Контракт — в разделе «Провайдеры СМС» ниже |
| IncludesController | `/api/admin/includes` | GET, POST, DELETE | Глобальные includes |
| SelfTestController | `/api/admin/self-test` | POST `run`, GET `modules` | Запуск self-test suite (`.bru` API-тесты против локального инстанса; `modules` — список доступных тестовых модулей). Включается ключом `SelfTest:Enabled` в `appsettings.json` |

**Гейт админки на конфигурационные сущности.** Чтение конфигурации кнопок действий в списке и наборов прав задач доступно только администратору. Эти сущности описывают устройство бизнес-процессов и матрицу прав, поэтому выдаются по административной роли, а не по признаку доступа к самой задаче.

**Вызов хранимых процедур и функций из API.** Администратор может выполнить любую хранимую процедуру или функцию платформы через `POST /api/admin/db/routines/execute`, передав её параметры. Для табличных функций поддерживается постраничный вызов (`Offset`, `Limit`), для функций PostgreSQL, возвращающих набор записей, — описание состава колонок (`Columns`).

## Ключевые настройки

### Общие настройки приложения (Settings)

**Где настраивается:** автоадминка → форма `system-settings`
**Таблица БД:** `dbo.Settings`

363 поля в 22 секциях. Крупнейшая форма в системе. Содержит глобальные флаги и лимиты:

| Секция (примеры) | Что контролирует |
|------------------|------------------|
| Общие | Имя системы, URL, таймзона |
| Файлы | Квоты, версионирование, провайдеры |
| Безопасность | Сложность паролей, блокировка, сессии |
| Почта | SMTP-параметры, шаблоны |
| Уведомления | Push, email-дайджесты |
| Интерфейс | Темы, локализация, логотип |
| Напоминание о конфиденциальности данных | Текст напоминания и режим повторного показа |

**Секция «Напоминание о конфиденциальности данных».** Секция задаёт текст тоста-напоминания, который видят пользователи в правом верхнем углу, и режим его повторного показа. Поле «Сообщение» — текст напоминания с разметкой; если оно пустое, напоминание не показывается никому. Флаг «Напоминать раз в сутки» задаёт периодичность: при включённом флаге напоминание показывается один раз в календарные сутки, при выключенном — однократно, до первого закрытия. Настройка не связана с согласием на обработку персональных данных и с прежними настройками коммерческой тайны.

| Обратная связь | Категория для обратной связи: пока поле заполнено, в меню профиля у пользователей есть пункт «Помощь», который открывает форму создания задачи в этой категории. Очистка поля убирает пункт из меню |

**Зависимости (deps):** 7 зависимостей между полями (условная видимость секций/полей).

**Настройка «Адрес перенаправления после выхода».**

**Где настраивается:** автоадминка → форма `system-settings`, секция «Основные настройки».
**Таблица БД:** `dbo.Settings`, колонка `LogoutRedirectUrl`.

Задаёт адрес, на который система возвращает пользователя после выхода из 1Формы. Раньше значение можно было задать только правкой колонки в базе; теперь поле есть в интерфейсе администрирования.

- Подходят и относительный внутренний путь (например, `/goodbye`), и полный адрес (например, `https://example.com`).
- Если поле пустое, используется адрес по умолчанию `/exit.html`.
- Настройка особенно полезна при входе через внешний провайдер: после выхода пользователя можно вернуть на корпоративный портал или страницу провайдера.
- Значение уходит на фронт вместе с настройками приложения; клиент читает его при выходе.

Техническая цепочка — в домене авторизации: backend.md (раздел про адрес перенаправления) и frontend.md (поведение сервиса авторизации).

**Эффект в runtime:** значения кэшируются в `SettingsService` и влияют на все домены приложения.

### Пользовательскые настройки (SettingsCustom)

**Где настраивается:** автоадминка → форма `custom-settings`
**Таблица БД:** `dbo.SettingsCustom`

Key/Value пары для доменных feature flags. Ключевые записи:
- `socialNetworksSettings` — конфигурация социальной сети
- `SpaceSettings` — конфигурация пространств
- Другие доменные настройки в формате JSON
- `ServiceAccountUserIds` — идентификаторы служебных учёток через запятую; по ним не пересчитываются системные тикеры, пользовательские индикаторы и дерево категорий

**Эффект в runtime:** читаются через `SettingsCustomService`, влияют на portal, social-network, spaces и другие домены.

📖 Полный перечень ключей с типами, значениями по умолчанию и описаниями — в справочнике [Пользовательскые настройки приложения (SettingsCustom)](https://help.1forma.ru/domains/system/settings-custom.md).

### Провайдеры: аутентификация, интеграции и файловые хранилища

**Провайдеры аутентификации.**

**Где настраивается:** автоадминка → форма `authentication-providers` / EntityEditor → `authenticationProviders`
**Таблицы БД:** `dbo.AuthenticationProviders`, `dbo.AuthenticationProviderGroups`

13 полей + 15 зависимостей: модель входа, поддерживаемые способы аутентификации, привязка к группам.

**Эффект в runtime:** определяет доступные способы входа в систему для разных групп пользователей.

**Интеграционные сервисы.**

**Где настраивается:** автоадминка → соответствующие формы `*-service-settings`
**Таблицы БД:** по одной таблице credentials на каждый сервис

Подключение к внешним системам: LDAP, OAuth, SAML, EWS, Diadoc, Sbis, Dadata, Tika, и т.д. Каждая форма содержит URL сервиса, учётные данные, параметры подключения.

**Файловые провайдеры.**

**Где настраивается:** EntityEditor → `fileProviders` / Admin API → `/api/admin/fileproviders`
**Таблица БД:** `dbo.FileProviders`

Провайдеры файлового хранилища. Влияют на домены `disk`, `files`, `ext-params`.

**Провайдеры СМС.**

**Где настраивается:** Администрирование → Провайдеры СМС (`~/spa/administration/sms-providers`); открывать и менять настройки может администратор площадки, назначение провайдера по умолчанию и тестовая отправка требуют прав суперадминистратора.
**Таблица БД:** `dbo.SMSProviders`; параметры подключения хранятся в XML-колонке `Settings`.

На страницу ведут пункт «Провайдеры СМС» панели администрирования и действие «Сервис отправки СМС» в форме «Общие настройки приложения»; старые адреса `/administration/entity/smsProviderSettings` и `/administration/entity/smsProviderSettings/1` перенаправляют на неё. Технический вид таблицы сохранён в форме автоадминки `sms-providers` и открывается только по прямому адресу.

Состав страницы:

- кнопка «Создать» — открывает карточку нового провайдера;
- блок «Провайдер по умолчанию» — выпадающий список и кнопка «Сохранить», активная только когда выбран другой провайдер; если провайдер по умолчанию не назначен, страница показывает подсказку «Провайдер по умолчанию не выбран — СМС не отправляются»;
- список провайдеров с колонками «ID», «Имя», «Сайт», «Класс», «По умолчанию»; клик по строке открывает карточку.

Карточка открывается в модальном окне («Создание провайдера» или «Редактирование провайдера») и содержит четыре группы:

| Группа | Поля |
|---|---|
| «Провайдер» | «Имя» (обязательное, до 100 символов), «Сайт» (до 200 символов), «Класс провайдера» (обязательный; у нового провайдера выбирается из справочника, у существующего показан только для чтения), «Провайдер по умолчанию» (только для чтения) |
| «Подключение» | «Адрес сервиса», «Логин», «Пароль», «API Id», «API Key», «API Secret», «Отправлять методом POST», «Callback Url», «Оплата только за доставленные», «Smtp сервер», «Smtp порт», «Email отправителя», «Использовать HTTPS», «Использовать прокси», «Адрес прокси сервера», «Логин прокси», «Пароль прокси» |
| «Отправители» | «Отправитель по умолчанию», «Отправитель 1Форма», «Дополнительный отправитель 1», «Дополнительный отправитель 2» |
| «Проверка отправки» | «Телефон для проверки», «Текст тестового сообщения», кнопка «Отправить тестовое СМС» |

Класс провайдера у существующего провайдера сменить нельзя — это запрещено и на стороне сервера.

**Состав полей подключения зависит от класса.** Страница запрашивает справочник классов и показывает только те поля, которые читает выбранный класс; при создании поля пересчитываются вместе с выбором класса. Скрытые поля на сервер не отправляются, поэтому сохранённые значения не затираются. Если класс не читает ни одного поля подключения, группа «Подключение» не показывается. В справочнике классов восемь классов провайдеров (с 2.268 «Скульптор»; ранее в него входили семь неиспользуемых иностранных провайдеров — BMI Telecom, Clickatell, Lancktele, Nexmo, Plivo, TXTNation, TelefonZentrale). **Остаточная запись удалённого провайдера:** если в справочнике провайдеров осталась запись с классом удалённого провайдера — обычно так на инсталляциях, где провайдера не удаляли, — класса в справочнике нет: карточка такого провайдера открывается без полей подключения, сохранённые настройки при этом не стираются, а отправка даёт контролируемую ошибку выбора провайдера. Запись следует удалить или заменить провайдером из действующего справочника. Поля «Адрес прокси сервера», «Логин прокси» и «Пароль прокси» дополнительно скрыты, пока не включён «Использовать прокси».

**Секреты не раскрываются.** В поле показывается заглушка сохранённого значения; под ней — подсказка о том, что оставленная заглушка секрет не меняет, очищенное поле удаляет, а новое значение заменяет сохранённое. Правило то же, что и в форме автоадминки.

**Проверка отправки.** Блок есть только у созданного провайдера — в карточке нового провайдера его нет. Если в карточке есть несохранённые изменения, сначала задаётся вопрос «Сохранить изменения и отправить тестовое СМС?»: тестовая отправка берёт настройки из базы, поэтому при подтверждении несохранённые значения сначала записываются, при отказе ничего не отправляется. Успешная отправка подтверждается сообщением «Тестовое сообщение отправлено»; при сбое показывается текст, который вернул провайдер, а при ошибке проверки данных — текст сервера, а не техническое сообщение об HTTP-ошибке. Пока идёт отправка, кнопка неактивна, поэтому повторный клик не отправляет второе сообщение.

**Проверка данных и закрытие карточки.** Обязательные поля — имя и класс провайдера. «Smtp порт» принимает только целое число от 1 до 65535 (при неверном значении — «Порт — целое число от 1 до 65535»). Попытка сохранить неверно заполненную форму даёт сообщение «Форма заполнена неверно — исправьте отмеченные поля», карточка остаётся открытой с введёнными данными. Закрытие карточки с несохранёнными изменениями требует подтверждения: «Изменения не сохранены. Закрыть карточку?». Кнопка «Сохранить» неактивна, пока форма не изменена.

**Чего на странице нет.** Удаление провайдеров не предусмотрено — ни на странице, ни в форме автоадминки (`AllowDeleteF = 0`). Настройки нового провайдера сохраняются только вместе с его созданием.

### Управление темизацией и бренд-цветом (AdminSPA)

**Где настраивается:** Администрирование → Системные настройки → Темизация (`/administration/theming`)

**Кто настраивает:** только главный администратор платформы; остальным доступ закрыт и на уровне API.

**Таблица БД:** `dbo.SettingsCustom`, ключ `ui-custom-tokens`

Экран задаёт фирменный бренд-цвет и оттенки группы токенов `primary` сразу для всей инсталляции — без ручной правки файлов конфигурации.

**Порядок настройки**

1. **Выбор бренд-цвета.** В списке «Бренд цвет» выбирается базовый цвет палитры дизайн-системы (`blue`, `red`, `green` и другие); по умолчанию — синий.
2. **Настройка оттенков.** Восемь полей задают оттенки для светлой и тёмной темы. Оттенок выбирается в рамках палитры выбранного бренд-цвета в формате «бренд-тон» (например, `red-700`); взять оттенки разных цветов палитры нельзя.
3. **Просмотр палитры.** Кнопка «Открыть палитру» открывает эталонный справочник токенов и оттенков шкалы дизайн-системы.
4. **Сохранение.** Кнопка «Сохранить» отправляет значения на сервер: они вливаются в сохранённые пользовательские токены, не затирая остальные кастомизации (например, `danger` или `warning`). Значения проверяются по палитре.
5. **Применение.** Обновлённый файл темы пересобирается фоном в течение нескольких секунд; после этого пользователи видят новую схему при обновлении страницы.
6. **Сброс.** Кнопка «Сбросить к теме 1Формы» возвращает заводские оттенки синего бренда платформы.

**Рекомендуемые оттенки**

| Тема | Токен | Назначение в интерфейсе | Рекомендуемый тон | Допустимый диапазон |
|---|---|---|---|---|
| Светлая | Base / Primary | фон основных кнопок, интерактивные текстовые ссылки | 700 | 400–800 |
| Светлая | OnBase / Primary | текст и иконки на брендовых кнопках | 100 | 0–200 |
| Светлая | Container / Primary | фон светлых и второстепенных бренд-кнопок и плашек | 150 | 100–200 |
| Светлая | OnContainer / Primary | текст и иконки на светлых бренд-кнопках | 850 | 800–1000 |
| Тёмная | Base / Primary | фон основных кнопок, интерактивные текстовые ссылки | 400 | 200–600 |
| Тёмная | OnBase / Primary | текст и иконки на брендовых кнопках | 950 | 800–1000 |
| Тёмная | Container / Primary | фон светлых и второстепенных бренд-кнопок и плашек | 900 | 800–1000 |
| Тёмная | OnContainer / Primary | текст и иконки на светлых бренд-кнопках | 300 | 200–600 |

### Фоновые задачи (Jobs)

**Где настраивается:** Admin API → `/api/admin/jobs`
**Маршрут:** `/api/admin/jobs`

Управление фоновыми задачами: просмотр состояния, блокировка/разблокировка, настройки расписания.

**Настройка расписания джоба.** Для фонового задания задаётся периодичность одного из типов: **Ежеминутно** (интервал в минутах, не меньше 1), **Ежедневно** (периодичность в днях, не меньше 1) или **Еженедельно** (нужно выбрать хотя бы один день недели). Типы **Ежемесячно** и **Ежегодно** для джобов не поддерживаются. Значения проверяются на сервере до сохранения: при недопустимом расписании запрос отклоняется с ошибкой, а запись в базу и применение к планировщику не выполняются.

**Защита от случайного закрытия.** Если форма настроек задания изменена и не сохранена, закрытие — кнопкой выхода, крестиком, клавишей Esc или кликом по фону — открывает вопрос «Сохранить изменения» с кнопками «Сохранить», «Не сохранять» и крестиком. «Сохранить» записывает настройки и закрывает окно только после успешной записи: при ошибке окно остаётся открытым с введёнными значениями. «Не сохранять» закрывает без записи, крестик оставляет форму в редактировании. Неизменённая форма закрывается сразу, без вопроса.

#### CustomSettings — параллелизм и таймауты QueuedHostedService

Ключи SettingsCustom, управляющие параллелизмом и таймаутами фоновой очереди задач.

| Ключ | Тип / Default | Назначение |
|------|---------------|------------|
| `BackgroundQueueMaxConcurrency` | int / `50` | Максимум фоновых задач, выполняемых одновременно в `QueuedHostedService`. При значении `1` задачи обрабатываются последовательно (поведение до v2.268) |
| `BackgroundQueueTaskTimeoutMinutes` | int / `10` | Таймаут одной фоновой задачи (мин). По истечении задача прерывается |
| `LazyJobsNumberOfItemsToProcessInBatch` | int / — | Размер batch'а, обрабатываемого за один тик `LazyUpdatableCachesUpdateJob` |
| `LazyJobsShowDetailedLog` | bool | Выводит подробные сообщения от `LazyUpdatableCachesUpdateJob` (ключи и значения) — используется для диагностики кэшей |
| `LazyQueueRetryLimit` | int / `5` | Максимум повторных попыток обновления одного кэша из очереди lazy-обновления (`LazyUpdatableCachesUpdateJob`); после исчерпания ключ переходит в терминальное состояние и не возвращается в очередь бесконечно |
| `LazyQueueTerminalRetryAfterSeconds` | int / `3600` | Пауза перед повторной попыткой (сек) для ключа в терминальном состоянии, исчерпавшего `LazyQueueRetryLimit` |
| `LazyQueueMaxSize` | int / `100000` | Потолок числа элементов в очереди lazy-обновления кэшей; при переполнении новые ключи не добавляются (защита от неограниченного роста) |
| `QuartzRunInClusterMode` | bool / `false` | Кластерный режим Quartz: координация запусков джобов между несколькими экземплярами приложения. По умолчанию выключен |
| `QueueEventsAmount` | int | Сколько событий обрабатывает джоб очереди за один запуск. Регулирует пропускную способность очереди событий. ⚠️ Действует **только** на штатный `QueueEventsJob` — ручной admin API `execute-errors` игнорирует эту настройку и всегда берёт не более 50 событий на поток |
| `DisableAllCachesUpdate` | bool / `false` | Отключает автоматическое обновление кэша после импорта конфигурации. Используется при массовых импортах для ускорения; после импорта кэш надо перестроить вручную |
| `CommitTransactionAfterSubcatIDChange` | bool / `false` | Если `true` — обновление ДП при переносе задачи между категориями (через `dbo.UpdateTaskSubcatIDIsClosed`) выполняется **вне** общей транзакции. Используется для обхода долгих блокировок |
| `MigrationExportSettings` | string (JSON) | Список типов объектов, исключаемых из экспорта конфигурации (см. процедуру экспорта-импорта). Применяется при миграциях между инсталляциями |

> Изменение `BackgroundQueueMaxConcurrency` влияет на нагрузку на CPU и пул соединений с БД. Поднимать выше 50 имеет смысл только при наличии свободных ресурсов и при подтверждённом «сужении» очереди задач.

**Глобальные includes (JS/CSS).**

**Где настраивается:** EntityEditor → `includes` / Admin API → `/api/admin/includes`
**Таблица БД:** `dbo.Includes`

Глобальные JS/CSS-вставки используются в актуальном админском контуре как рабочий функционал (не только legacy).

Для грида включений в AdminSPA endpoint `GET /api/includes/get-all` возвращает список включений с привязкой к подкатегориям:

- `Id`
- `Type`
- `Name`
- `Guid` — сквозной идентификатор вставки (`dbo.Includes.GUID`): присваивается при создании и при редактировании не перевыставляется, поэтому по нему сопоставляют одну и ту же вставку на разных площадках, а числовой `Id` на каждой площадке свой. Перенос объектов по `Guid` — в [домене «Миграция»](https://help.1forma.ru/domains/migration/README.md)
- `Subcategories[{Id, Name}]`

![Список глобальных JS/CSS-вставок в AdminSPA](https://help.1forma.ru/help-images/system/includes_list.png)

**Создание и изменение через API.** Вставку можно создать и обновить через Admin API:

- `POST /api/admin/includes` — создать вставку; тело `{Description, Type, Content}`, ответ — `Id` созданной вставки;
- `POST /api/admin/includes/{includeId}` — обновить вставку (перезапись всех полей).

`Type` задаёт вид вставки: `1` — JS, `2` — CSS, `3` — внешний JS по URL. При обновлении `Type` нужно передавать всегда: без него тип сбрасывается в значение по умолчанию и JS-вставка перестаёт исполняться. Оба вызова требуют прав администратора и пишут запись в журнал админ-действий.

## Типичные ошибки настройки

Наиболее частые проблемы при администрировании системных настроек и способы их диагностики.

| Симптом | Причина | Где проверить | SQL-диагностика |
|---------|---------|---------------|-----------------|
| Пользователи не могут войти после смены auth-провайдера | Неверная привязка провайдера к группам | Форма `authentication-providers` | `select ap.*, apg.GroupId from dbo.AuthenticationProviders ap left join dbo.AuthenticationProviderGroups apg on ap.Id = apg.ProviderId` |
| Интеграционный сервис «включён», но не работает | Неверные credentials | Соответствующая форма `*-service-settings` | `select * from dbo.{ServiceTable}` |
| Проблемы с файлами после правок infrastructure | Неверный файловый провайдер | EntityEditor `fileProviders` | `select * from dbo.FileProviders` |
| Фоновые процессы не исполняются | Job заблокирован или неверные настройки | `/api/admin/jobs` | Проверить состояние через API |
| UI нестабилен после изменения global settings | Критичные флаги в Settings | Форма `system-settings` | `select * from dbo.Settings` |
| Доменная функция не работает | Неверный ключ в SettingsCustom | Форма `custom-settings` | `select * from dbo.SettingsCustom where [Key] = '{keyName}'` |

## Глобальные настройки платформы (форма system-settings)

> Форма `system-settings` содержит 363 поля в 22 секциях. Ниже описаны ключевые инварианты и смысловые кластеры, критичные для администрирования.

### Критические инварианты — ⚠️ необратимые или неочевидные настройки

**HSTS (HTTP Strict Transport Security).**

Настройка: **Использовать HSTS**. После включения все браузеры, хоть раз заходившие на площадку, запоминают флаг и требуют HTTPS.

⚠️ **Настройка необратима.** После включения её нельзя отключить — пользователи, получившие HSTS-заголовок, не смогут зайти по HTTP до истечения срока действия заголовка. Администратор не может принудительно сбросить кеш HSTS в браузерах пользователей.

**Квота личной папки на Диске.**

Настройка: **Квота личной папки пользователя в файловом хранилище** (байты).

- Значение по умолчанию: **5 GB** (5 368 709 120 байт).
- ⚠️ Если значение **не задано или равно 0** — папка «Мои файлы» раздела Диск **недоступна** для всех пользователей. Без квоты файловый раздел полностью выключен.
- Квота распространяется на все файлы, где пользователь является владельцем (кто вложил файл). Файлы в задачах и чатах не учитываются.
- Для загрузки файлов > 300 МБ требуются дополнительные изменения в системных файлах приложения.

**Минимальное количество символов для поиска.**

Настройка: **Количество обязательных символов для поиска**.

⚠️ **Принудительный минимум — 3 символа**, независимо от значения настройки. Поиск по 1–2 символам невозможен. Ограничение действует на:

- Общий поиск в панели навигации
- Меню «Сотрудники»
- Табличное представление списка задач (кроме числовых колонок)
- ДП «Lookup-поле» и «Выбор пользователей» в карточке задачи

Не распространяется на режим администрирования. Значение транслируется в параметр `NumberCharactersForSearch` файла `app-settings.json`.

### Делегирование, наследование прав и регистрация — инварианты (часть 2)

**Делегирование подписи.**

Настройка: **Пользователь всегда может делегировать свою подпись**.

- Если настройка **включена** — пользователь может делегировать подпись, если у подписи есть такая резолюция. Право доступа «Добавлять и менять акцептантов» в категории **не проверяется**.
- Если настройка **отключена** — делегирование доступно только при наличии права «Добавлять и менять акцептантов» в категории.

⚠️ Частая причина несоответствия ожиданий при разграничении доступа к делегированию подписи.

**Руководитель наследует право просмотра.**

Настройка: **Руководитель наследует право на просмотр задач, где его подчинённые — заказчики или исполнители**.

⚠️ После изменения этой настройки автоматически вызывается `GenerateExtParamRightsFunctions` — пересчёт прав для всех категорий с ДП-доступом. На крупных инсталляциях пересчёт может занять значительное время.

Настройка учитывает только роль пользователя в задачах, независимо от прав доступа в категории. По умолчанию руководители **не** наследуют право доступа по группам на просмотр всех задач категории от подчинённых; включить такое наследование можно через пользовательскую настройку `ForbidSubcatRightsInheritanceToDirector`.

**Обязательные поля профиля при самостоятельной регистрации.**

Настройка: **Обязательные поля профиля пользователя** (Дата рождения, Псевдоним, E-mail, Внешний E-mail).

⚠️ Если в пользовательской настройке `RegistrationFields` (ключ SettingsCustom) задан блок `PasswordSettings` или список обязательных полей — он имеет **приоритет выше**, чем флаги в форме `system-settings`. Это относится только к форме самостоятельной регистрации.

**Удаление истории акцептантов подписи.**

Настройка: **Удалять историю акцептантов подписи после обработки**.

- Если настройка **включена** — после обработки подписи в БД остаётся только фактически подписавший. Информация о том, у кого была запрошена подпись, теряется.
- Если настройка **отключена** — сохраняется и первоначальный акцептант, и фактически подписавший.

Важно для контроля деятельности заместителей: если заместитель подписал за руководителя, при выключенной настройке видно, что подпись была запрошена у руководителя, а обработана заместителем.

### Системные сущности

**Администраторская группа.**

Настройка: **Администраторская группа**.

Только пользователи указанной группы видят интерфейс администрирования. Если группа не задана — административный UI закрыт для всех.

**Системные категории.**

| Категория | Поле в форме | Назначение |
|-----------|-------------|------------|
| Личные задачи | Категория для личных задач | Создание личных задач пользователей |
| Ошибки | Категория для ошибок | Регистрация ошибок. Если категория задана, в модальном окне ошибки отображается кнопка «Создать задачу в техподдержку»: по нажатию в этой категории сразу создаётся задача с технической информацией об ошибке. Чтобы кнопка не показывалась, поле можно очистить, однако так делать не рекомендуется: возможность сообщить об ошибке должна быть у всех пользователей |
| Обратная связь | Категория для обратной связи | Вопросы пользователей по использованию системы |
| Анонимные задачи | Категория для анонимных задач | Задачи, создаваемые от имени анонимного пользователя для автоматизации |

Каждая категория назначается отдельным полем. Если не задана — соответствующая функция недоступна.

**Системные пользователи.**

| Пользователь | Поле в форме | Назначение |
|-------------|-------------|------------|
| Пользователь для анонимных публикаций | Пользователь для анонимных публикаций | Создание анонимных задач |
| Диспетчер задач | Диспетчер задач | Создание объектов с опцией «от имени диспетчера задач» |
| Робот нотификатор | Робот нотификатор | Рассылка уведомлений о пропущенных звонках |

**Системные подписи.**

| Подпись | Поле в форме | Назначение |
|---------|-------------|------------|
| Подпись заказчика | Подпись заказчика | Запрашивается при завершении задач, если у заказчика включено «Требует акцепта всех своих задач» |
| Подпись пользователя | Подпись пользователя | Используется как личная динамическая подпись. ⚠️ Заполняется автоматически при инсталляции — **изменять не рекомендуется** |
| Подпись на согласование трудозатрат | Подпись на согласование плановых трудозатрат | Запрашивается при согласовании плановых трудозатрат |
| Подпись на согласование исполнителей | Подпись на согласование плановых исполнителей | Запрашивается при согласовании плановых исполнителей |

**Группы по умолчанию.**

| Группа | Поле в форме | Назначение |
|--------|-------------|------------|
| Группа по умолчанию | Группа по умолчанию для новых пользователей | Назначается новым пользователям с признаком «Сотрудник компании» |
| Группа для внешних | Группа для внешних пользователей | Назначается пользователям без признака «Сотрудник компании» |

> **Не указывайте здесь группу «Все пользователи»** — она системная, её состав формируется автоматически (любой созданный пользователь добавляется в неё сам). Явная привязка через поле «Группа по умолчанию для новых пользователей» приводит к попытке редактирования состава системной группы, и при создании пользователя выдаётся ошибка «Состав группы нельзя редактировать».

> **Эта же настройка используется при обновлении для портальных блоков.** Блоки порталов, у которых не было ни одной группы доступа, при обновлении получают группу отсюда: пустой список групп означает отсутствие доступа, поэтому без такой подстановки задуманные доступными блоки исчезли бы у всех, кроме администратора. Если настройка не заполнена или ссылается на несуществующую группу, подстановка не выполняется. Подробнее — [admin.md](https://help.1forma.ru/domains/portal/admin.md).

### Логирование производительности

#### Логирование смарт-операций (4 порога)

Каждый вид логирования имеет отдельное поле и независимый порог (мс):

| Вид логирования | Поле в форме | Минимум | Рекомендация | Значение 0 |
|----------------|-------------|---------|-------------|------------|
| Смарт-запросы | Логировать время выполнения smart запросов дольше мс. | 100 мс | 200 мс | Логировать все |
| Смарт-действия | Логировать время выполнения smart действий дольше мс. | 100 мс | 200 мс | Логировать все |
| Пакеты действий | Логировать выполнение smart пакетов действий дольше мс. | 100 мс | 200 мс | Логировать все |
| Смарт-доступ | Логировать выполнение smart доступа дольше мс. | 100 мс | 200 мс | Логировать все |

⚠️ Минимально допустимое значение — **100 мс**. Значения < 100 система не позволит сохранить.

С v2.264 Кассиопея логирование пакетов действий также охватывает **смарт-расписания**.

Результаты записываются в **журнал выполнения автоматизации** (таблица `AutomationLog`).

**SQL-логирование.**

Настройка: **Логировать SQL запросы** (мс, по умолчанию 200 мс).

При наличии пользовательской настройки `LogPlanExecution` (SettingsCustom) для запросов, превысивших указанный в ней порог, дополнительно формируется **план выполнения** и записывается в колонку «План запроса» журнала автоматизации. ⚠️ Функция планов выполнения — **только PostgreSQL**.

**Глубина рекурсии смарт-пакетов.**

Настройка: **Глубина рекурсии смарт-пакетов** (default = 10).

При превышении глубины рекурсивных вызовов смарт-действия в рамках одного потока (TaskID + UserID + контекст) генерируется ошибка в журнале ошибок. Не применяется к пакетам, выполняющимся в рамках расписаний и циклических пакетов.

#### Сроки хранения журналов

Все настройки задаются в Общих настройках приложения. Старые записи удаляются автоматически (housekeeping-джобы).

| Журнал | Параметр | Default |
|--------|----------|---------|
| **Журнал ошибок** | Срок хранения в логе ошибок истории (дни) | 14 дней |
| **Журнал звонков** | Время жизни записи в журнале звонков | 7 дней |
| **Журнал действий с файлами** | Время жизни записи в журнале действий с файлами | 7 дней |
| **Журнал активности пользователя** | Срок хранения информации о активности пользователя в системе | 14 дней |

Сроки хранения журнала действий и журнала автоматизаций, в отличие от строк выше, задаются в **Пользовательских настройках приложения** (автоадминка → форма `custom-settings`): ключи `ActionLogDaysKept` и `AutomationScriptsLogDaysKept`, раздел «Журналы». Пустое значение оставляет прежние сроки: журнал действий — 7 дней для девяти шаблонов и 14 дней для записей «Smart доступ», журнал автоматизаций — 7 дней. Положительное число задаёт свой срок, `0` отключает чистку по этому журналу. Ключи появляются в таблице настроек после первого обращения, с пустым значением.

⚠️ Большой срок хранения **увеличивает размер таблиц-журналов** и может отрицательно сказаться на быстродействии. Перед увеличением — проверьте дисковое потребление и индексы.

Связанные настройки активности:

| Параметр | Назначение |
|----------|------------|
| **Включить мониторинг активности пользователя в системе** | Если включено — ведётся журнал онлайн-времени пользователей |
| **Включить мониторинг действий пользователя в мобильном приложении** | Если включено — в `UserCounters` / `UserCountersLog` пишутся вход/комментарии/просмотры из МП |
| **Время неактивности (мин)** | Период неактивности, после которого пользователь считается **оффлайн** (имя в UI не подсвечивается зелёным) |
| **Интервал обновления в оффлайне (мин)** | Как часто браузер обновляет счётчик непрочитанных, когда пользователь оффлайн, но вкладка с 1Ф открыта |

> Активность определяется per-tab: при сворачивании браузера или переключении на другую вкладку 1Ф учитывает это для счётчика конкурентных лицензий (`ConcurrentSessionMinLengthInMinutes`).

#### Журнал отказов по правам (access-denied.log)

Штатный отказ по правам (ответ 403) сбоем приложения не считается: он пишется на уровне `Warn`, а в «Лог ошибок» (таблица `ExceptionsLog`) NLog пишет с уровня `Error`. В интерфейсе «Лог ошибок» такие отказы не отображаются — там остаются непредвиденные серверные сбои.

Отказы по правам уходят в отдельный файл на сервере приложений — `logs/<дата>/access-denied.log` в каталоге приложения. Каталог с датой заводится на каждый день, файл ротируется по достижении 10 МБ и хранит до десяти архивов. Запись содержит то же, что и прочие файловые логи приложения: время, уровень, описание исключения с причиной отказа, стек вызовов, IP, referrer, данные запроса и его идентификатор.

Отдельный источник записи — импорт значений ДП из CSV: если в файле оказались строки с недоступной задачей, номером, которого нет в системе, или нулевым либо отрицательным номером, на запрос пишется одна запись со списком отклонённых номеров. Значения ДП по этим строкам не меняются, а в результате импорта каждая из них получает сообщение об отсутствии доступа.

### Требования к паролям

⚠️ Параметры данного блока применяются **только** к созданию/сбросу паролей пользователей из режима администрирования. Для самостоятельной регистрации требования задаются в пользовательской настройке `RegistrationFields` (блок `PasswordSettings`).

| Параметр | Поле в форме | Описание |
|---------|-------------|----------|
| Срок действия | Срок действия пароля (дни) | Только для Forms-авторизации. При просрочке — принудительная смена |
| Мин. длина | Минимальная длина пароля | Если не задано — без ограничения |
| Макс. длина | Максимальная длина пароля | Если не задано — без ограничения |
| Спецсимволы | Пароль должен содержать минимум один символ, не являющийся буквой или цифрой | !, @, #, $, % |
| Заглавные буквы | Пароль должен содержать минимум одну заглавную букву | Хотя бы одна прописная |
| Запрет совпадения с логином | Пароль может совпадать с логином | При включении — совпадение разрешено |
| История паролей | Длина истории паролей | Количество предыдущих паролей, запрещённых к повторному использованию |
| Проверка даты рождения | Проверять пароль на наличие даты рождения | Запрещает пароль, содержащий дату рождения пользователя |
| Клавиатурные ряды | Минимальная длина последовательности символов для проверки | Цифры (123…), алфавит (abc…), клавиатурные ряды (йцукен/qwerty/azerty и т.д.) |
| Повторяющиеся паттерны | Минимальная длина повторяющегося паттерна для проверки | Например, qweqwe, 123123. Только непосредственный повтор, не разрозненный |

### Дизайн карточки задачи МТФ (v2.264 Кассиопея)

Блок настроек доступен начиная с версии 2.264. Позволяет кастомизировать внешний вид карточки задачи.

**Фон и обводка полей.**

| Настройка | Значения |
|-----------|---------|
| Включить фон полей МТФ | on/off (default = off) |
| Цвет фона полей МТФ | `default`, `primary`, `level-zero`, `level-one`, `level-two`, `level-three` |
| Включить обводку полей МТФ | on/off (default = off) |
| Цвет обводки полей МТФ | `default`, `shallow`, `base`, `deep`, `primary` |

**Блоки МТФ.**

| Настройка | Значения |
|-----------|---------|
| Стиль фона блоков МТФ | `default` (по умолчанию), `none` (без фона), `color` (цветной) |
| Цвет фона блоков МТФ | `default`, `primary`, `level-zero`, `level-one`, `level-two`, `level-three` (только при стиле `color`) |

**Иконки, аватары, кнопки.**

| Настройка | Значения |
|-----------|---------|
| Цвет иконок ДП МТФ | `default`, `brand`, `primary`, `secondary`, `tertiary` |
| Цвет аватаров | Цветные (по умолчанию) / Брендовые / Серые — единый цвет на всю площадку, не затрагивает аватары чатов и задач |
| Стиль базовых кнопок | По умолчанию, Стиль 1, Стиль 2, Стиль 3 — применяется в карточке создания, модальных окнах, интерфейсе администрирования |

### Привязки ДП модуля ресурсов

Следующие 14 настроек задают привязку к дополнительным параметрам (ДП) модуля ресурсов. Расположены в форме `system-settings`.

**ДП справочника ресурсов.**

| Настройка | Тип ДП | Назначение |
|-----------|--------|------------|
| Тип ресурса | Выпадающий список | Типы: трудовой, затратный и т.д. |
| Подтип | Выпадающий список | Подтипы: сотрудник, материальный, внешний и т.д. |
| Основные исполнители | Выбор пользователей | Основные исполнители элемента справочника |
| Дополнительные исполнители | Выбор пользователей | Дополнительные исполнители |
| Внутренний исполнитель | Выбор пользователей | Внутренние исполнители |
| Единица измерения | Текст | Единица измерения элемента |
| Владелец ресурса | Выбор пользователей | Владелец элемента справочника |
| Ответственный за ресурс | Выбор пользователей | Ответственный за элемент |
| Группы, обладающие правом планировать ресурс | Выбор пользователей | Группы планирования |
| Утверждение трудозатрат | Выбор пользователей | Ответственные за утверждение |
| Блокирование трудозатрат | Выбор пользователей | Ответственные за блокирование |

**Сводные разделы и подписи.**

| Настройка | Назначение |
|-----------|------------|
| Сводный раздел типов ресурсов | ID сводного раздела со всеми типами ресурсов |
| Сводный раздел экземпляров ресурсов | ID сводного раздела со всеми экземплярами |
| Подпись на согласование плановых трудозатрат | Подпись для согласования трудозатрат (в секции ресурсов) |
| Подпись на согласование плановых исполнителей | Подпись для согласования исполнителей (в секции ресурсов) |

### Инфраструктурные и административные настройки

**Миграционный ключ (dev-режим).**

Настройка: **Миграционный ключ** — число от 1 до 9. Активирует dev-режим для переноса конфигурации между средами (dev → test → prod). Кнопка «Перевести сервер в dev-режим» в верхней части формы `system-settings`.

**Денормализатор.**

Настройка: **Категории, исключаемые из полной денормализации**. Категории с большим количеством ДП предпочтительнее денормализовать вручную — их исключают из полной денормализации.

**Доступные языки.**

Настройка: **Доступные языки** — JSON-массив:

```json
[{"Id":1,"Name":"Русский","Available":true}, {"Id":2,"Name":"English","Available":true}, ...]
```

Параметры: `Id` = ID из таблицы `Languages`, `Name` = название (`LangDescr`), `Available` — доступен для выбора.

⚠️ Языки с признаками `IsDefault` и `IsInternational` в таблице `Languages` **нельзя** отключить.

**Обработка персональных данных.**

Настройка: **Требовать подтверждение согласия на обработку персональных данных**.

При включении — при первой авторизации пользователю отображается форма с текстом соглашения (поле `Текст соглашения`). Пользователь не сможет войти без подтверждения. Проверяется поле `IsAgreeToStorePersonalData` в таблице `Users`.

Если настройка отключена — отметка о согласии не проверяется и согласие не запрашивается.

**Напоминание о конфиденциальности данных.** Секция идёт сразу за «Обработкой персональных данных» и с ней не связана: блокирующее окно согласия при входе работает независимо.

| Настройка | Описание |
|-----------|----------|
| Сообщение | Текст напоминания о конфиденциальности данных. Длина не ограничена; пустое значение равнозначно ненастроенному напоминанию |
| Напоминать раз в сутки | Режим повторного показа напоминания |

Прежние настройки коммерческой тайны — текст, показ логотипа и разрешение его скрывать — с формы сняты, а в справочнике колонок помечены как устаревшие. Сохранённые значения при этом не удалялись.

**Кеширование задач.**

| Настройка | Описание |
|-----------|----------|
| Количество записей для загрузки | Число записей при полном обновлении кеша (0 = без ограничения) |
| Категории без ограничения | Список категорий, по которым записи выгружаются без ограничения количества |

**Провайдер карт.**

Настройка: **Провайдер карт**. Поддерживается только **Bing** — требуется уникальный API-ключ. Используется в отчётах геолокации.

**Синхронизация с Exchange (настройки в system-settings).**

⚠️ Форма `system-settings` содержит настройки синхронизации с Exchange **напрямую**, независимо от сервиса EWS (форма `ews-service-settings` в разделе «Подключения»).

| Параметр | Описание |
|---------|----------|
| Адрес EWS | URL Exchange Web Service |
| Исключаемые категории Exchange | Список через `;` |
| Режим работы с сервисами Exchange | Автоматическое включение для новых пользователей |
| Синхронизация событийная | При каждом изменении календарной задачи |
| Синхронизация периодических встреч | Синхронизация повторяющихся встреч |
| Порог давности событий (дни) | Не синхронизировать события старше N дней; 0 = все |
| Макс. неудачных попыток | При превышении пользователь исключается из синхронизации; 0 = без ограничения |
| Перевоплощение | Служебный пользователь перевоплощается в организатора встречи (менее приоритетно, чем аналогичная опция в `ews-service-settings`) |
| Доменная авторизация | Для сервера в домене (on) / в рабочей группе (off) |
| Логин / Пароль / Домен | Учётные данные служебного пользователя синхронизации |

**Как хранится пароль.** Пароль служебного пользователя Exchange и параметры подключения SharePoint хранятся в базе зашифрованными мастер-ключом площадки. При сохранении общих настроек значение шифруется, если оно не расшифровывается ключом этой площадки; значение, пришедшее из базы или кеша при правке соседних полей, повторно не шифруется. Значение, зашифрованное ключом другой площадки — например, после переноса базы, — восстановить нельзя: при сохранении оно зашифруется поверх, поэтому пароль и параметры подключения нужно ввести заново.

**Кастомный лоадер SPA.** Настройка «Кастомный лоадер SPA (Lottie JSON)» в секции «Веб-приложение» формы `system-settings` заменяет стандартный волновой экран загрузки SPA на кастомную векторную анимацию Lottie. В поле вставляется содержимое Lottie JSON, для правки есть редактор JSON в модальном окне. Ограничение — 512 КБ текста; применяется после перезапуска пула приложений, потому что разметка экрана загрузки генерируется при старте. Поведение одинаково на Windows и Linux.

При корректном значении стандартные «волны» не показываются ни на один кадр: правило, скрывающее их, встраивается в `<head>` страницы до запуска скриптов, а в разметку экрана загрузки добавляются сама анимация и её плеер. Анимация зациклена, при переходе приложения в рабочее состояние ставится на паузу, при повторном показе экрана загрузки продолжается.

Если поле пустое, JSON невалиден или превышен лимит, кастомный загрузчик не подставляется: в журнал записывается ошибка, пользователь видит штатный загрузчик, старт приложения не блокируется. Если плеер анимации не загрузился в браузере, штатный загрузчик возвращается на место. После очистки поля и перезапуска пула вставки из `index.html` удаляются.

## Кеши — управление и мониторинг (AdminSPA)

В разделе **Система → Кеши** для каждого кеша выводится статистика использования и меню действий.

**Столбцы статистики:**

| Столбец | Значение |
|---|---|
| Размер | Текущий размер кеша |
| Кол-во использований | Число попаданий в кеш (`totalHits`) |
| Промахи | Число промахов (`totalMisses`) |
| Эффективность | Доля попаданий: `totalHits / (totalHits + totalMisses) × 100`, до двух знаков |

Если статистика по кешу недоступна, столбцы «Кол-во использований», «Промахи» и «Эффективность» остаются пустыми.

**Действия по кешу** собраны в меню «три точки» в колонке «Действия»:

- Получить все ключи;
- Получить значение;
- Получить первые 100 записей;
- Обновить кеш.


Полное обновление кэша на одной ноде рассылает команду всем нодам кластера. Нода, инициировавшая обновление, перезаполняет кэш сразу; остальные ноды начинают загрузку каждая со своим сдвигом в пределах окна (см. настройку сдвига в справочнике пользовательских настроек приложения). Поэтому тяжёлый кэш не перезаполняется на всех нодах одновременно, а в течение окна после правки другие ноды могут отдавать прежние данные.

Не у каждого кэша доступны все действия. Кэш, который реализует интерфейс кэша явно, без наследования базового класса, не поддерживает перечисление ключей: при выборе действия «Получить все ключи» вместо списка система показывает отказ «Перечисление ключей этим кэшем не поддерживается» (в тексте отказа указан тип кэша). Остальные действия по такому кэшу работают как обычно, а его участие в событийной инвалидации и удалении пропускается с записью в журнал сервера — ошибка на экран не выводится.

В поставке платформы таких кэшей нет: все встроенные кэши наследуют общий базовый класс. Отказ возможен только для кэша, добавленного расширением или модулем с явной реализацией интерфейса. Столбцы «Кол-во использований», «Промахи» и «Эффективность» остаются пустыми, если статистика по кэшу недоступна; так же пусто может быть значение «Последнее полное обновление» — оно заполняется только у кэшей, поддерживающих инвалидацию.

Все полные обновления кэша на ноде идут через общий ограничитель: для каждого типа кэша одновременно выполняется не более одной загрузки, повторные запросы склеиваются с ней, а время одной загрузки ограничено настройкой «Предел времени полной загрузки кэша» (по умолчанию 600 секунд, см. справочник пользовательских настроек). Поэтому обновление кэша из админки при медленном или зависшем чтении из первоисточника завершается не позже предела и показывает прежние данные, а не ошибку: кэш продолжает отдавать прежний снимок, а в журнал записываются имя кэша и длительность загрузки.
## appsettings.json — справочник системных ключей

Параметры в `appsettings.json` загружаются при старте приложения. Большинство — серверная инфраструктура; **повторное прочтение конфига** на горячую — не поддерживается, нужен restart. Для динамических переключений используйте `CustomSettings` (см. выше) или общие настройки приложения.

### Корневые ключи (root)

Ключи верхнего уровня `appsettings.json`, не входящие в именованные секции.

| Ключ | Тип / Default | Назначение |
|------|---------------|------------|
| `Urls` | string | Адреса прослушивания Kestrel: `<схема>://<хост>:<порт>` через `;`. Игнорируется при работе под IIS. ⚠️ Приоритет ниже, чем у `ASPNETCORE_URLS` и `--urls` |
| `AllowedHosts` | string / `*` | Разрешённые `Host`-заголовки. `*` — все |
| `MaxRequestLength` | int (байты) / `2 ГБ` | Максимальный размер HTTP-запроса (ограничение на загрузку файлов) |
| `MultipartBodyLengthLimit` | int (байты) / `134 217 728` (~128 МБ) | Размер каждой части `multipart/form-data` |
| `OutboundHttpAllowed` | bool / `false` | Разрешает приложению любые исходящие HTTP-запросы (превью ссылок и т. п.). Для метаданных — лимит 2 МБ |
| `OutboundHttpProxy` | string (URL) | Прокси для всех исходящих HTTP-запросов |
| `LicensesKey` | string | Принудительная установка ключа лицензии |

> 📌 Ключи из определённых секций работают **как в своей секции, так и в корне** файла (cв. с источника).

### `Server` и `Application` — конфигурация сервера и шины сообщений

**`Server`.**

| Ключ | Назначение |
|------|------------|
| `IsMainServer` | Главный сервер. Если `IsJobServer` не задан явно, джобы запускаются здесь |
| `IsJobServer` | Сервер заданий по таймеру. При `true` на старте поднимается механизм Jobs |

**`Application` (только эти ключи входят в эту секцию).**

| Ключ | Default | Назначение |
|------|---------|------------|
| `MessageBus` | — | Провайдер шины сообщений: `None` / `RebusSQL` / `RebusPostgre`. Значение `Redis` оставлено для чтения старых конфигов и больше не запускается: старт с ним падает с ошибкой. Для MSSQL используйте `RebusSQL`, для PostgreSQL — `RebusPostgre` |
| `RebusLoggerType` | `None` | Тип лога Rebus: `None` / `Console` / `NLog` |
| `RebusLogLevel` | — | Уровень: `None` / `Debug` / `Info` / `Warn` / `Error` (накопительно: `Debug` включает всё выше) |
| `ApplicationInstanceId` | — | Уникальное имя очереди для шины сообщений. ⚠️ Без `-` (только `_`) |
| `JobServerMaxConcurrency` | `10` | Максимум параллельных заданий по таймеру (Quartz Jobs) |
| `BackgroundQueue:MaxConcurrency` | `5` | Параллелизм `QueuedHostedService` (async SmartRule, ответы Анфисы, фоновые скрипты, кэши). При `1` — последовательное выполнение |

### Корневые ключи без секции (системные)

Системные ключи, которые задаются в корне `appsettings.json` вне именованных секций и управляют глобальным поведением платформы.

| Ключ | Тип / Default | Назначение |
|------|---------------|------------|
| `IsCachingDisabled` | bool | Полное отключение кэширования (для отладки) |
| `IsDevelopmentMode` | bool | Отключает кодовые миграции на старте |
| `CodeMigrationsIsEnabled` | bool | Включение/отключение миграций БД |
| `DisableAllCachesUpdate` | bool | Отключает auto-обновление кэша после импорта конфигурации |
| `DontUseGetMachineIPForLog` | bool | Не использовать IP машины в логах (анонимизация) |
| `IgnoreDomainCheck` | bool | Отключает разрешённые домены — подключение с любого хоста |
| `InvalidateUsersCacheByEvent` | bool / `false` | Инвалидация `UsersCache` по сигналу мастер-сервера. ⚠️ Не рекомендуется без подтверждённого сценария |
| `DisableSqlShell` | bool / `false` | Скрывает в UI пункт «Выполнить SQL-запрос», кнопку «В TSQL» в редакторе и блокирует редактирование процедур (403) |
| `SwaggerIsEnabled` | bool / `false` | Swagger UI и `swagger.json` доступны только в окружении Development или при `true` (в остальных окружениях выключены — и регистрация сервисов, и middleware). Отключение ломает внешних потребителей `swagger.json` |
| `DisableAQB` | bool / `true` | Отключение AspQueryBuilder. Default — выключен. Включается явным `false` |
| `DefaultIsolationLevel` | int / `2` (`ReadCommitted`) | Уровень изоляции транзакций. ⚠️ С v2.261 «Лира» рекомендуется `2` |
| `UseTransactionOnTaskSynchronization` | bool | Использовать транзакцию при синхронизации задач |
| `IsSpaHost` | bool / `true` | Генерация SPA-файлов брендирования в локальную ФС |
| `UseSpaPortals` | bool | Использование новых порталов в **старом** фронте |
| `UsePostgreSQLDatabase` | bool | Используется PostgreSQL (vs MS SQL) |
| `Use404Logger` | bool | Логирование 404 в журнал автоматизации |
| `EnableRemovalOfUnusedFiles` | bool | Включает джобы удаления неиспользуемых файлов. ⚠️ На тестовом сервере с боевыми файловыми провайдерами **не включать** — удалит файлы и в проде |
| `RemovalOfUnusedFilesBatchCount` | int | Лимит файлов на один прогон `RemovePreparedFileStorageFilesJob` |
| `FilesCacheSize` | int (МБ) / `500` | Размер файлового кэша |
| `FilesExtensionsToNotCache` | string | Расширения, не попадающие в кэш (через запятую) |
| `WinToFormsRedirectFormsUrl` / `WinToFormsRedirectWinUrl` | URL | Базовые адреса forms- и win-приложений для редиректа между ними |
| `OpenLDAPProtocolVersion` | int / `3` | Версия LDAP-протокола |
| `ExcludeAdSubdomains` | string | Исключённые поддомены (для дерева, AD-синхронизации, поиска) |
| `PhoneProfileLocation` | string | Идентификатор локации телефонии (для нескольких контуров) |
| `RestrictAbsenceMessageForAll` | bool | Ограничить сообщение об отсутствии для всех пользователей |
| `logoutRedirectUrl` | URL / `/exit.html` | Куда редиректить пользователя после logout. С 2.268 значение настраивается в интерфейсе — форма «Общие настройки приложения», поле «Адрес перенаправления после выхода»; правка `appsettings.json` не требуется |
| `ProviderType` / `Name` / `Id` (на уровне auth-провайдера) | — | Тип провайдера, имя, идентификатор (`SAML`/`OAuth`/...) |

### Доменно-специфичные корневые ключи

> Доменно-специфичные корневые ключи вынесены в соответствующие admin.md:
> - `IsExchangeSyncServer`, `UseExchangeAutodiscover`, `ExchangeTraceListenerFlags`, `CreateTasksForAppointments` → [`calendar/admin.md`](https://help.1forma.ru/domains/calendar/admin.md);
> - `DecodeEdsSignatures` → [`signatures/admin.md`](https://help.1forma.ru/domains/signatures/admin.md);
> - `UseClassicEncodeInComments` → [`comments/admin.md`](https://help.1forma.ru/domains/comments/admin.md);
> - `UseHacksForMailSending` → [`mail/admin.md`](https://help.1forma.ru/domains/mail/admin.md);
> - `UseDevexpressDocToPdfConverter` → [`files/admin.md`](https://help.1forma.ru/domains/files/admin.md);
> - `ActiveDirectoryAuthenticationMode`, `AuthUseInsecureCookies`, `SetCookieForUpperLevelDomain`, `WinAuthHost` → [`auth/admin.md`](https://help.1forma.ru/domains/auth/admin.md).

### `ConnectionStrings` и `ForwardHeaders` — строки подключения и прокси

Секция `ConnectionStrings` задаёт строки подключения к БД и шине сообщений; `ForwardHeaders` — настройки для развёртывания за прокси или TLS-терминатором.

| Ключ | Назначение |
|------|------------|
| `TCConnectionString` | Основная БД TaskCenter. ⚠️ `MultipleActiveResultSets=false` |
| `RebusConnectionString` | Шина сообщений Rebus. Работает и с `MultipleActiveResultSets=true`, и с `MultipleActiveResultSets=false`. На Linux с MARS драйвер SqlClient под нагрузкой может не забирать уже пришедшие ответы сервера, и потоки шины встают ([dotnet/SqlClient#422](https://github.com/dotnet/SqlClient/issues/422)); без MARS этого пути нет |
| `SmartConnectionString` | Отдельный пул для TSQL-выражений и «Выполнить SQL-запрос». Если не задан — используется `TCConnectionString`. Относится к выражениям с собственным T-SQL: выражения в режиме XML-формулы и смарт-фильтры считаются по основной строке и от этого ключа не зависят. ⚠️ `MultipleActiveResultSets=false` |
| `SmartPgConnectionString` | PG-пул для PGSQL-вариантов смарт-выражений. Без него — кнопка «Тест PGSQL» и чип PGSQL не отображаются (используется для тестирования PG-скриптов с MSSQL-стенда) |
| `SignalRedisConnectionString` | Redis для SignalR-сигналинга (`<host>:<port>,Password=...`) |
| `VectorDbConnectionString` | **[deprecated 2026-05-08]** PostgreSQL для legacy `vector_search` namespace (AI Search). При наличии — регистрируется JS API `VECTORDB` (`query` / `query_one` / `scalar`); иначе SmartScript использует Npgsql fallback. Ключ оставлен для совместимости. |

**Про `RebusConnectionString` и `MultipleActiveResultSets`.** Перед приёмом сообщения и перед отправкой берётся блокировка подключения, поэтому на одном соединении не выполняется две команды одновременно, и для обслуживания очереди шины `MultipleActiveResultSets=true` не требуется. На остальные строки подключения это не распространяется.

⚠️ Параметры строк подключения: `Data Source`, `Initial Catalog`, `User ID`, `Password`, `Persist Security Info`, `Max Pool Size`, `Min Pool Size`, `Connect Timeout`, `Encrypt`, `packet size`.

**`ForwardHeaders` (для развёртывания за прокси / TLS-терминатором).**

| Ключ | Значения | Назначение |
|------|----------|------------|
| `Headers` | `*` / `None` / `For` / `Host` / `Proto` / `Prefix` (через запятую) | Какие `X-Forwarded-*` заголовки обрабатывать |
| `Networks` | список IP / `*` | Известные сети |
| `Proxies` | список IP / `*` | Известные прокси |

Без этой секции ASP.NET не подменяет схему/хост из заголовков — получаются ошибки в перенаправлениях для HTTPS-сайтов за HTTP-прокси.

### `Telemetry` (OpenTelemetry) и `Logging` (NLog/Serilog)

**`Telemetry` (OpenTelemetry).**

| Ключ | Default | Назначение |
|------|---------|------------|
| `EnableTracing` | bool | Включает трассировку |
| `EnableMetrics` | bool | Включает сбор метрик |
| `OtlpEndpoint` | `http://localhost:4317` | Конечная точка OTLP для метрик/трасс/логов |

**`Logging` — стандартная секция .NET.**

Конфигурируется через NLog (файл `NLog.config` приложения) и Serilog. Версия NLog в репозитории закреплена явно — 6.0.6; она действует и на приложение, и на тестовые проекты ядра, поэтому локальная сборка и CI работают на одной версии. Секция `Logging` в `appsettings.json` нужна только для перенаправления в стандартные приёмники .NET: правила, цели и уровни задаются файлом `NLog.config`.

## Системные маршруты — типичные ошибки и связанные документы

Наиболее частые ошибки при работе с системными маршрутами администрирования.

| Операция | Неправильно | Правильно |
|----------|-------------|-----------|
| Очистка кеша | `/api/system/cache/clear`, `/api/admin/cache/clear` → 404 | `POST /api/system/updateallcaches` |
| Hostname стенда PG | проверить корректность DNS-зоны (.ru vs .net) | использовать актуальный хост из конфига |


