Обновить документацию под глобальную конфигурацию ИИ
ci / build-test (pull_request) Successful in 2m58s

ТЗ, api-map, техническая документация, инструкция пользователя и контракт операторских настроек: настройки ИИ-провайдера перенесены в консоль оператора, пользовательский POST /api/ai/check удалён.
This commit is contained in:
2026-09-15 21:59:43 +03:00
parent 6b7bfa5e4d
commit ea4ed73327
5 changed files with 114 additions and 33 deletions
@@ -119,8 +119,10 @@ global_settings(key, value, updated_at)
> `token_usage_events` — история расхода токенов (этап 10, T2; подробнее — §13.10).
> `global_settings` — глобальные настройки уровня сервиса; сейчас хранит ключи приложения Telegram
> (`telegramKeys`: `api_id`/`api_hash`, hash — в `enc:`), которые задаёт **оператор** глобально
> (ручки `GET/PUT /api/operator/settings/telegram-keys`); тенант ключи не видит/не задаёт.
> (`telegramKeys`: `api_id`/`api_hash`, hash — в `enc:`) и конфигурацию ИИ-провайдера (`aiConfig`:
> `providerId`/`baseUrl`/`model`/`apiKey` — в `enc:`), которые задаёт **оператор** глобально
> (ручки `GET/PUT /api/operator/settings/telegram-keys` и `/ai-config`, проверка связи —
> `POST /api/operator/settings/ai-config/check`); тенант эти настройки не видит и не задаёт.
> Операторские таблицы этапа 7 (`operators`, `operator_sessions`, `tenant_limits`, `audit_log`) и их
> контур описаны в §13.8. С этапа 12 счётчики распределённого rate-limit и попыток входа —
> `public.rate_limit_counters` (см. §10).
@@ -496,7 +498,8 @@ DEAL_MTLS_ENABLED=0|1 DEAL_MTLS_CERT_PASSWORD=... DEAL_DEFAULT_AI_BU
ответ — полный снимок; секреты наружу только масками `keyMasked`/`apiId`; внутренние ключи
`ratesCache`/`mlDecisions`/`aiDecisions` не публикуются);
- шифрование секретов AI/Telegram: AES-256-GCM, в БД — `enc:` + Base64 (ключ — env/file, см. §13.4a);
- проверка подключения ИИ: `POST /api/ai/check` (локальный провайдер / HTTP-проверка облачного);
- проверка подключения ИИ: `POST /api/operator/settings/ai-config/check` (операторская; локальный провайдер /
HTTP-проверка облачного);
- курсы валют: `GET /api/rates`, `POST /api/rates/refresh` (кэш `ratesCache` в settings; `mock`/ЦБ);
- ML-панель на детерминированной заглушке: `GET /api/ml/status`, `POST /api/ml/reset|predict`
(candidates → `{items:[]}`, apply → 404 — нет telegram-данных до этапа 6);
@@ -774,28 +777,30 @@ health — `GET /api/health` → `{"ok":true,"service":"deal"}`.
### 4a. Шифрование секретов настроек (ключи AI/Telegram)
Секреты (`aiConfigs[].apiKey`) хранятся в `settings.ValueJson` шифротекстом:
`enc:` + Base64(nonce‖ct‖tag), AES-256-GCM (nonce 12 Б, tag 16 Б). Ключ шифрования — env
`DEAL_ENCRYPTION_KEY` (32 байта в urlsafe-Base64); при отсутствии в dev берётся/создаётся файл
`<ContentRoot>/data/encryption.key` (путь переопределяется env `DEAL_ENCRYPTION_KEY_FILE`) —
при генерации лог-warning. Невалидный env-ключ — ошибка при старте. Наружу секреты не отдаются:
в GET/PATCH `/api/settings` только маски `keyMasked` (первые 4 + «…» + последние 4, len≤8 — как есть)
Секреты хранятся шифротекстом `enc:` + Base64(nonce‖ct‖tag), AES-256-GCM (nonce 12 Б, tag 16 Б).
Ключ шифрования — env `DEAL_ENCRYPTION_KEY` (32 байта в urlsafe-Base64); при отсутствии в dev
берётся/создаётся файл `<ContentRoot>/data/encryption.key` (путь переопределяется env
`DEAL_ENCRYPTION_KEY_FILE`) — при генерации лог-warning. Невалидный env-ключ — ошибка при старте.
Наружу секреты не отдаются: только маски `keyMasked` (первые 4 + «…» + последние 4, len≤8 — как есть)
и `keySet`.
> Исторический раздел (этап 2). С этапа 12 ключей Telegram (`tgKeys`/`apiId`/`apiHash`) в настройках
> тенанта нет — они задаются **оператором** глобально (таблица `public.global_settings`,
> `GET/PUT /api/operator/settings/telegram-keys`; hash шифруется тем же AES-256-GCM).
>
> С 2026-09-14 там же живёт и конфигурация ИИ-провайдера (ключ `aiConfig` в `public.global_settings`,
> `GET/PUT /api/operator/settings/ai-config`): провайдер, модель, baseUrl и API-ключ задаёт оператор,
> все ИИ-вызовы всех тенантов идут на эту конфигурацию; в настройках тенанта ключей `aiProvider`/
> `aiConfigs` больше нет.
### 4b. Эндпоинты этапа 2 (настройки тенанта; сессия `deal_session` обязательна, иначе 401)
- `GET /api/settings` — публичный снимок дерева настроек: дефолты модуля, перекрытые
переопределениями из `settings` тенанта; включает списки `providers`/`aiConfigs`/`tgKeys`/`myPrompts`.
переопределениями из `settings` тенанта; включает `myPrompts` и колонки, но не настройки
ИИ-провайдера (они операторские).
`PATCH /api/settings` — частичное обновление (невалидное поле мягко пропускается, ответ — полный
снимок). Побочные эффекты: при `rateSource` — фоновый refresh курсов. Внутренние ключи
(`ratesCache`, `mlDecisions`, `aiDecisions`) в GET/PATCH не участвуют.
- `POST /api/ai/check` — проверка подключения активного провайдера (`aiProvider` + `aiConfigs`, ключ
расшифровывается): локальный провайдер → `ok:true` «Локальный сервер…»; облачный — HTTP `GET
{base}/models`; без ключа → «Не задан API-ключ».
- `GET /api/rates` / `POST /api/rates/refresh` — курсы к RUB (`base` = `RUB`); источник по `rateSource`
(`mock` — константа, `cbr` — ЦБ РФ, ≤4 запроса/сутки, интервал 6 ч; `USDT`=`USD`); кэш — внутренняя
настройка `ratesCache` `{rates, source, updatedAtMs}`.
@@ -1149,8 +1154,9 @@ docker compose -f deploy/compose.dev.yml down # погасить ст
(`PUT /api/operator/settings/telegram-keys`, hash шифруется) → `POST /api/tg/start-qr` → QR-скан →
фаза `ready` («Telegram подключён, сессия сохранена»), затем реальные диалоги/мониторинг/«Перечитать»/
discovery-поиск и вступления. В настройках тенанта ключей нет (решение владельца, вариант A).
- LLM: `PATCH /api/settings` `aiConfigs`/`aiProvider` (напр. DeepSeek или локальный OpenAI-совместимый) →
`POST /api/ai/check`; реальная классификация/фильтр/генерация ключей при `Services__Ai__UseLocal=false`.
- LLM: оператор задаёт провайдера и модель в консоли (`PUT /api/operator/settings/ai-config`, напр. DeepSeek
или локальный OpenAI-совместимый) → `POST /api/operator/settings/ai-config/check`; реальная
классификация/фильтр/генерация ключей при `Services__Ai__UseLocal=false`.
- Сквозной smoke стека — `scripts/dev-smoke.sh` (одна команда; Docker Desktop должен быть поднят).
### 8. Этап 7 — SaaS-контур (Tasks 114; бэкапы — §13.9; финальные доки — Task 16): оператор/инвайты/лимиты/аудит/rate-limit/mTLS/логи/compose-prod