# Документация модуля Settings (Настройки)

## Введение

Модуль `Knot.Modules.Settings` является централизованным компонентом для управления глобальными конфигурациями и параметрами системы в архитектуре модульного монолита (Modular Monolith) Knot Messager. Он обеспечивает единый источник истины (Single Source of Truth) для настроек всех других модулей (WebRTC, Federation, Messages, Chats, Admin и др.).

## Основные принципы (DDD и Clean Architecture)

- **Независимость и Инкапсуляция:** Модуль выступает как самостоятельная единица и не зависит от реализаций других модулей. Другие модули ссылаются на `Settings` только через абстракции или контракты.
- **Единственный Источник Истины:** Любое изменение системной конфигурации (включение/отключение фич, лимиты, домены) происходит через этот модуль.
- **Событийная Модель (Domain Events):** При изменении настроек инфраструктура Settings генерирует доменное событие `SystemSettingsUpdatedDomainEvent`, позволяя другим модулям (например, `Federation` для отправки новых Capabilities) реагировать на изменения асинхронно, не создавая жестких связей.

## Структура модуля

Модуль спроектирован по принципам Чистой Архитектуры и разделен на слои:

```text
Knot.Modules.Settings/
├── Application/                   # Слой Приложения (Application Layer)
│   ├── Settings/
│   │   ├── Abstractions/          # Определение интерфейсов доступа к каждому разделу настроек
│   │   │   ├── ISettingsService.cs
│   │   │   ├── IMessagesSettings.cs
│   │   │   ├── IWebRtcSettings.cs
│   │   │   └── ...
│   │   ├── DTOs/                  # Структуры данных конфигураций
│   │       ├── SystemSettingsDto.cs
│   │       ├── PublicConfigDto.cs
│   │       ├── KlipyConfig.cs
│   │       └── ...
├── Domain/                        # Доменный Слой (Domain Layer)
│   ├── Events/
│   │   └── SystemSettingsUpdatedDomainEvent.cs   # Событие об изменении настроек
├── Infrastructure/                # Слой Инфраструктуры (Infrastructure Layer)
│   ├── Configuration/
│   │   └── SettingsService.cs     # Реализация логики кэширования и обновления
├── DependencyInjection.cs         # Регистрация модуля в DI (AddSettingsModule)
```

## Как это работает?

### 1. Интерфейсы сегрегации (Interface Segregation Principle - ISP)

Чтобы модули не зависели от огромного объекта настройки всей системы `SystemSettingsDto`, в слое `Application/Settings/Abstractions/ISettingsService.cs` мы разделили конфигурации на интерфейсы по специализациям:

- `ISystemSettings` — Системные и общие параметры.
- `IWebRtcSettings` — Настройки аудио/видео вызовов (WebRTC, TURN).
- `IMessagesSettings` — Настройки сообщений (файлы, ограничения).
- `IFederationSettings` — Настройки ActivityPub/Федерации.
- `IKlipySettings` — Настройки интеграции внешней библиотеки гифок (Klipy).

### 2. Доступ к настройкам из других модулей

Если, например, модулю бесед (Conversations) требуется проверить, включены ли интеграции Klipy, он инжектит специфичный интерфейс `IKlipySettings`, не получая доступа к настройкам админки или WebRTC:

```csharp
public class CreateStoryCommandHandler
{
    private readonly IKlipySettings _klipySettings;

    public CreateStoryCommandHandler(IKlipySettings klipySettings)
    {
        _klipySettings = klipySettings;
    }

    public async Task Handle(...)
    {
        if (!_klipySettings.Current.Enabled) {
            // Отбросить логику
        }
    }
}
```

### 3. Хранение и шифрование данных

Реализация `SettingsService` хранит данные централизованно (в таблице `SystemSettings` БД через `SystemDbContext` в `Knot.Shared.Infrastructure`) в формате JSON.
Для безопасности вся JSON-строка **зашифрована** с использованием `IEncryptionService`.

Особенности хранения:
- **Кэширование**: `SettingsService` зарегистрирован как `Singleton`. При запуске сервера конфигурация загружается один раз из базы данных (или кеша/файла) и сохраняется в памяти.
- **Обновление**: Метод `UpdateSettingsAsync` сохраняет новый стейт в БД и обновляет объект в памяти (`_current`), предотвращая лишние запросы к базе данных при обычной работе мессенджера. 

## Жизненный цикл обновления настроек (Управление)

Администратор изменяет настройки через UI (или API), после чего происходит следующий процесс:

1. Вызывается эндпоинт в модуле **Admin**: `PUT /api/admin/settings`.
2. Команда `UpdateSettingsCommand` валидирует входные данные.
3. Команда обращается к `ISettingsService.UpdateSettingsAsync(newSettings)`.
4. `SettingsService` шифрует новые настройки, обновляет запись в БД, и заменяет кэш в оперативной памяти.
5. После успешного сохранения, диспетчер MediatR (в `Admin` модуле) публикует `SystemSettingsUpdatedDomainEvent`.
6. Событие отлавливается через `INotificationHandler<SystemSettingsUpdatedDomainEvent>` независимыми слушателями, например:
   - Модулем `Federation` для рассылки всем "соседним" инстансам новых возможностей `Capabilities`.

## Регистрация модуля

При старте приложения в `Host/Program.cs` модуль инициализируется:

```csharp
// Регистрация сервисов модуля настроек
builder.Services.AddSettingsModule(builder.Configuration);

// Дополнительно можно вызывать Initialize(...) чтобы загрузить кэш из БД при старте
```

Под капотом `DependencyInjection.cs`:
```csharp
public static IServiceCollection AddSettingsModule(this IServiceCollection services, IConfiguration configuration)
{
    services.AddSingleton<SettingsService>();
    
    // Привязываем конкретные абстракции к одному Singleton инстансу
    services.AddSingleton<ISettingsService>(sp => sp.GetRequiredService<SettingsService>());
    services.AddSingleton<IMessagesSettings>(sp => sp.GetRequiredService<SettingsService>());
    // ... и остальные
}
```

## Публичная конфигурация клиента (PublicConfig)

Для клиентской части (Frontend) предусмотрен специальный DTO объект `PublicConfigDto`. 
Это subset (урезанная часть) от `SystemSettingsDto`, которая не содержит чувствительной информации о сервере и ключах:

- Доступные лимиты медиа файлов.
- Включены ли аудио/видео звонки.
- Включена ли федерация для поиска глобальных пользователей.

Таким образом, клиент может запросить `GET /api/app/config`, а бэкенд отдаст безопасный набор доступных разрешений через маппинг `SettingsService.Current`.
