К документации
Руководство 03

Конфигурация

Simmetric Chat имеет два уровня конфигурации: переменные окружения, проверяемые с помощью Zod при запуске процесса, и уровень конфигурации времени выполнения, хранящийся в базе данных, который администраторы могут редактировать через интерфейс без переза…

3 мин чтения

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

  1. Переменные окружения (запуск процесса) - проверяются с помощью Zod в packages/<pkg>/src/config/env.ts; process.exit(1) при невалидности.
  2. Конфигурация времени выполнения (DB `SystemConfig`) - редактируется через UI администратора без перезапуска.

Разрешение:

  • Ключи ALWAYS_READONLY (JWT_SECRET, DATABASE_URL, SERVER_PORT, COLLECTOR_PORT, SERVER_URL, COLLECTOR_URL, LICENSE_SECRET): ENV > Default, не редактируются через UI.
  • Все остальные: DB > ENV > Default, редактируются через PUT /api/system/settings.

Все три пакета читают .env через path.resolve(__dirname, "../../.env") (независимо от рабочей директории). Эталонный документ — .env.example в корне репозитория.

Переменные окружения - server

Схема: packages/server/src/config/env.ts. Показаны значения по умолчанию; ОБЯЗ = обязательно.

Core / инфраструктура

ПеременнаяDefaultОбязат.Описание
NODE_ENVdevelopmentoptdevelopment/production/test
SERVER_PORT3000optПорт API сервера
COLLECTOR_PORT3210optПорт collector (для URL по умолчанию)
SERVER_URLhttp://localhost:3000optПубличный URL сервера
COLLECTOR_URLhttp://localhost:3210optURL collector
WIDGET_SERVICE_URLhttp://localhost:3211optURL сервиса виджета (push cache-bust)
WIDGET_API_KEY—optОбщий секрет push виджета; при отсутствии cache-bust — no-op (TTL 5 мин)
DATABASE_URLpostgresql://simmetricchat:[email protected]:5432/simmetricchatoptURL PostgreSQL
JWT_SECRET—ОБЯЗСекрет JWT
ENCRYPTION_KEY—optBase64 32 байт для AES-256-GCM (data-at-rest). Не задан → fallback scryptSync(JWT_SECRET, salt)
SESSION_EXPIRY86400000 (24ч мс)optСрок действия JWT
ALLOWED_ORIGINShttp://localhost:5173,127.0.0.1:5173,localhost:3000optГлобальный allowlist CORS (CSV). /api/internal/widget исключён
LOG_LEVELinfooptdebug/info/warn/error
ALLOW_REGISTRATIONfalseoptПереключатель саморегистрации
DISABLE_TELEMETRYtrueoptОтключает телеметрию

Bootstrap-админ (seed)

ПеременнаяDefaultОписание
SEED_BOOTSTRAP_ADMINtrueАвто-сид админа при первом запуске (custom transform: false/0/no/off/"" = отключено)
SEED_ADMIN_USERNAMEadminИмя пользователя bootstrap-админа
SEED_ADMIN_PASSWORDadmin123Пароль (мин 8); аккаунт mustChangePassword=true
SEED_ADMIN_EMAIL[email protected]Email bootstrap-админа

LLM

ПеременнаяDefaultОписание
LLM_PROVIDERollamaopenai/anthropic/ollama/openrouter
LLM_MODELgemma4:latestМодель по умолчанию
LLM_TEMPERATURE0.70–2
LLM_MAX_TOKENS4096Лимит токенов завершения
LLM_TIMEOUT0Таймаут Axios в мс (0 = нет, для медленных локальных LLM)
LLM_API_KEY / LLM_API_BASE_URL—Общие переопределения
OPENAI_API_KEY / OPENAI_MODEL—OpenAI
ANTHROPIC_API_KEY / ANTHROPIC_MODEL—Anthropic
OLLAMA_BASE_URLhttp://ollama:11434Эндпоинт Ollama
OLLAMA_MODEL / OLLAMA_API_KEY—Ollama override
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODELhttps://openrouter.ai/api / —OpenRouter

Watchdog агента (предотвращение циклов/зависаний)

ПеременнаяDefaultОписание
AGENT_WALLCLOCK_TIMEOUT_MS600000 (10 мин)Абсолютный верхний предел для ReAct-запроса
AGENT_MAX_TOTAL_TOKENS200000Итого prompt+completion на запрос
AGENT_MAX_CONTEXT_BYTES500000 (500 КБ)Лимит размера массива контекста
AGENT_MAX_TOOL_OUTPUT_LENGTH5000Усечение вывода на навык
AGENT_MAX_SKILL_EXECUTION_MS60000Таймаут на навык
AGENT_LOOP_DETECTION_WINDOW3Прерывание после N одинаковых подряд tool+input
CHAT_MAX_CONCURRENT_PER_USER5Лимит одновременных чатов на пользователя

Embedding / Vector DB / OCR / Synthesis

ПеременнаяDefaultОписание
EMBEDDING_PROVIDERlocallocal/openai/ollama
EMBEDDING_MODELXenova/all-MiniLM-L6-v2Модель эмбеддингов
EMBEDDING_API_KEY—API-ключ эмбеддингов
VECTOR_DB_PROVIDERlancedblancedb/qdrant
VECTOR_DB_URL / VECTOR_DB_API_KEY—Для удалённого Qdrant
OCR_MODELglm-ocr:latestМодель зрения OCR (формат model:version)
OCR_TIMEOUT600000Таймаут зрения OCR
SYNTHESIS_LLM_MODELgemma4:latestМодель конвейера синтеза
PUPPETEER_EXECUTABLE_PATH—Chromium для экспорта PDF архивов

Лицензия, push, email, collector

ПеременнаяDefaultОписание
LICENSE_KEY—JWT лицензии Enterprise (HS256). Отсутствует → Community
LICENSE_SECRET—Секрет проверки JWT (рекомендуется); fallback на LICENSE_KEY
COLLECTOR_SECRET—ОБЯЗ — общий секрет server↔collector
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT—Web Push; не заданы → эфемерные ключи в dev
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM—SMTP для сброса пароля + уведомлений о сбое бэкапа
LEGACY_PREVIOUS_ENCRYPTION_KEYS—CSV base64 32-байтные ключи для ротации
Переменные в .env.example, но управляемые как DB settings (не в envSchema): OCR_ENABLED, OCR_PRECHECK_CHARS, STORAGE_PATH (collector), RESET_PASSWORD_STRATEGY.

Переменные окружения - collector

Схема: packages/collector/src/config/env.ts.

ПеременнаяDefaultОбязат.Описание
COLLECTOR_PORT3210optHTTP-порт
COLLECTOR_URLhttp://localhost:3210optСобственный URL
SERVER_URLhttp://localhost:3000optURL сервера (callback)
EMBEDDING_PROVIDERlocaloptlocal/openai/ollama
EMBEDDING_MODEL—optМодель эмбеддингов
EMBEDDING_API_KEY—optAPI-ключ
VECTOR_DB_PROVIDERlancedboptlancedb/qdrant
VECTOR_DB_URL / VECTOR_DB_API_KEY—optQdrant
OLLAMA_BASE_URLhttp://ollama:11434optOllama
STORAGE_PATH./storageoptФайловое хранилище
COLLECTOR_SECRET—ОБЯЗДолжен совпадать с сервером

Переменные окружения - widget

Схема: packages/widget/src/config/env.ts.

ПеременнаяDefaultОбязат.Описание
NODE_ENVdevelopmentoptОкружение
WIDGET_PORT3211optHTTP-порт
SERVER_URLhttp://localhost:3000optURL сервера
WIDGET_API_KEY—ОБЯЗОбщий секрет widget↔server (должен совпадать)
LOG_LEVELinfooptУровень логов
Frontend: нет переменных VITE_* и файла .env. Фронтенд читает брендинг/конфиг с сервера (GET /api/system/settings, GET /api/license/info).

Feature flags и лицензия

Определены в packages/shared/src/constants/license.ts (FEATURE_FLAGS + defaults). Проверка в packages/server/src/services/licenseService.ts.

Как перейти с Community на Enterprise

  1. Задайте LICENSE_KEY (JWT HS256) и, рекомендуется, LICENSE_SECRET.
  2. jwt.verify → payload валидируется против licensePayloadSchema (tier, iss, sub, iat, exp, features).
  3. tier=enterprise → стартует с ENTERPRISE_FEATURE_DEFAULTS + override features из JWT.
  4. Истёкшая/невалидная → fallback Community с предупреждением.

Graceful degradation: getLicenseInfo() проверяет срок действия в рантайме; если Enterprise истекает во время работы, она деградирует до Community без перезапуска. requireFeature(flag) → HTTP 402, если отключено; requireFeatureLimit(flag, model) → 402, когда count >= limit (Enterprise = Infinity).

Всегда включённые commodity-флаги: после удаления EPA-02 8 commodity-флагов больше не существуют в FEATURE_FLAGS - webhooks, push_notifications, web search, memory, lead_export, widget_analytics, auto_title, synthesis_rate_limit всегда включены в Community (commodity-маршруты работают без гейтинга). priority_support — не флаг: это коммерческий/SLA-контракт (EPA-08). Осталось 11 enterprise-флагов, включая widget_credits_editing (редактирование кредитов виджета, Community false / Enterprise true) и custom_agents как числовой лимит (Community 3, Enterprise Infinity).

Таблица флагов (11)

ФлагТипCommunityEnterpriseЧто гейтит
sso_enabledboolfalsetrueSSO Enterprise
audit_log_immutableboolfalsetrueНеизменяемость audit-лога
white_labelboolfalsetrueБрендинг BRANDING_*
max_workspacesnum3InfinityСоздание рабочих пространств
max_projectsnum3InfinityСоздание проектов
custom_agentsnum3InfinityКастомные агенты (лимит)
widget_enabledboolfalsetrueВстраиваемый виджет
max_widgetsnum1InfinityСоздание виджетов
backup_enabledboolfalsetrueСистема бэкапов
max_backup_destinationsnum1InfinityНазначения бэкапов
widget_credits_editingboolfalsetrueРедактирование кредитов виджета

Конфигурация времени выполнения (DB SystemConfig)

Редактируется через GET/PUT /api/system/settings (bulk) и PUT /api/system/chat-retention (специфичный, аудируемый). Defaults живут в CONFIG_DEFAULTS (packages/shared/src/constants/permissions.ts).

Группы ключей: LLM (LLM_PROVIDER, LLM_MODEL, LLM_TEMPERATURE, ...), Embedding/Vector, Порты/URL сервера, Auth (SESSION_EXPIRY), Брендинг (BRANDING_APP_NAME, BRANDING_PRIMARY_COLOR, BRANDING_APP_SUBTITLE, BRANDING_APP_ICON_URL - gated white_label), Feature (DISABLE_TELEMETRY, ALLOW_REGISTRATION, DLP_ENABLED), OCR (OCR_DEFAULT_MODEL, OCR_DEFAULT_MODE, OCR_DEFAULT_CUSTOM_INSTRUCTIONS, OCR_ENABLED, OCR_PRECHECK_CHARS), Synthesis (SYNTHESIS_LLM_PROVIDER_ID, SYNTHESIS_LLM_MODEL), Retention (upload_draft_retention_days, ALLOW_NON_ADMIN_UPLOAD, chat_message_retention_days).

PUT /api/system/settings всегда возвращает 200 с { updated: [...], rejected: [...] } (readonly-ключи отклоняются, остальные применяются).

Хранение сообщений чата (reaper)

Сервис: packages/server/src/services/chatMessageReaperJob.ts. DB-ручка: chat_message_retention_days.

  • Pass 1 (soft-delete): tombstone сообщений АКТИВНЫХ чатов за пределами retentionDays. No-op, если значение null/""/<=0.
  • Pass 2 (hard-purge): удаляет tombstone-строки за пределами 7-дневной отсрочки (hardcoded). Запускается всегда, независимо от конфигурации хранения (анти-утечка PII).
  • Каденция: setInterval 24ч, первый запуск в 03:00 по местному времени. Мьютекс isRunning.
  • Только PUT /api/system/chat-retention (аудируемый, confirmDataLoss: true, retentionDays: integer|null, мин 1); bulk-settings эндпоинт отклоняет этот ключ.

Хранение бэкапов

По заданию (поле retentionDays на BackupJob, default 30). backupRetentionService.ts очищает логи/файлы за пределами cutoffDate. Не глобально.

Ротация ключей шифрования

packages/server/src/services/encryptionService.ts (AES-256-GCM, ключ 32 байта, IV 16 байт, соль simmetric-chat-encryption-salt).

  • Текущий ключ: ENCRYPTION_KEY (base64 32 байта), если задан; иначе scryptSync(JWT_SECRET, salt, 32).
  • LEGACY_PREVIOUS_ENCRYPTION_KEYS (CSV base64 32 байта) → цепочка ключей дешифрования [current, ...previous, scryptLegacy?].
  • encrypt() использует chain[0]. Автоматического re-encryption-задания нет: процедура ручная — расшифровать-старым → зашифровать-новым.