# ТЗ-плюс — уточнения и дополнения от заказчика > Основа: `docs/ТЗ.md` > Дата последнего обновления: 2026-06-04 > Файл для фиксации уточнений, дополнений и решений. --- ## 1. Аутентификация — интеграция с IAM API ### 1.1. IAM API — единый сервис авторизации (УТОЧНЕНО 04.06.2026) IAM (Identity & Access Management) — сервис авторизации экосистемы Nubes. Все смежные сервисы ходят в него для проверки компании пользователя. **Три стенда:** | Стенд | URL | |---|---| | Dev | `https://auth-api-dev.ngcloud.ru` | | Test | `https://auth-api-test.ngcloud.ru` | | Prod | `https://auth-api.ngcloud.ru` | **Swagger:** `https://auth-api-dev.ngcloud.ru/api/v1/documentation/` **Исходный источник:** CRM Elma (контакт, компания, отношение N:M). **Статус:** 🟢 подтверждено ### 1.2. Поток аутентификации (УТОЧНЕНО 04.06.2026) ``` Пользователь → Keycloak (SSO) → IAM (обмен code) → access_token + refresh_token │ ┌───────────────────────────────┘ ▼ GET /api/v1/auth/user (Bearer access_token) │ ▼ { profiles[], userInfo } ``` `access_token` от IAM (token_type: "access", TTL 12 часов) сразу годится для вызова `GET /api/v1/auth/user`. Никакого дополнительного обмена не требуется. **Статус:** 🟢 подтверждено (Node.js HTTP 200, получен реальный ответ) ### 1.3. client_id приложения в Keycloak - **Источник:** HAR-файл - **Факт:** `client_id` в URL auth-запроса - **Статус:** 🔴 требует подтверждения ### 1.4. JWKS URL и Redirect URI - **Статус:** 🔴 требует подтверждения DevOps --- ## 2. Компании пользователя — IAM /auth/user ### 2.1. `GET /api/v1/auth/user` (УТОЧНЕНО 04.06.2026) **Реальный ответ** (пользователь `tazetdinovn@gmail.com`, prod): ```json { "profiles": [ { "id": 4357, "client_id": "WZ03709", "company_id": "019cc24a-727e-740f-b407-bec79dab4162", "company_name": "naeel_test", "company_numeric_id": 2645, "is_active_profile": true } ], "userInfo": { "clientID": "WZ03709", "company": "naeel_test", "companyId": "019cc24a-727e-740f-b407-bec79dab4162", "companyNumericId": 2645, "email": "tazetdinovn@gmail.com", "isAdmin": false, "fio": {"fullName": "Тазетдинов Наиль Фаритович", "name": "Наиль", "secondName": "Фаритович", "surname": "Тазетдинов"}, "contactId": "019cc268-6c6a-781e-8613-4bed4ec7cd20", "elmaUserId": 39715 } } ``` **Маппинг полей для использования в коде:** | Назначение | Откуда | |---|---| | Список WZ-кодов компаний | `profiles[].client_id` | | Активная компания | `profiles[].is_active_profile === true` | | ID для switch-profile | `profiles[].id` | | WZ активной компании | `userInfo.clientID` | | Название компании | `userInfo.company` | | UUID компании | `userInfo.companyId` | | Флаг админа | `userInfo.isAdmin` | | Email | `userInfo.email` | **Статус:** 🟢 подтверждено ### 2.2. `POST /api/v1/user/switch-profile` (УТОЧНЕНО 04.06.2026) Тело: `{"profile_id": 3120}` или `{"company_id": "uuid"}`. **Статус:** 🟡 уточнено по Swagger, не тестировалось на живом multi-company юзере ### 2.3. ⚫ ClientID через запятую в JWT — УСТАРЕЛО - **Было (01.06):** `ClientID: "WZ11125, WZ03816"` в claims JWT - **Стало (04.06):** JWT содержит только ОДНУ компанию (активную). Правильный источник списка — `profiles[]` из IAM API. - **Статус:** ⚫ отменено ### 2.4. ⚫ Admin = WZ01112 — УСТАРЕЛО - **Было:** `clientId === 'WZ01112'` → админ - **Стало:** `userInfo.isAdmin` из IAM API - **Статус:** ⚫ отменено --- ## 3. Сетевая доступность ### 3.1. ddos-guard (УТОЧНЕНО 04.06.2026) Все `*.ngcloud.ru` за ddos-guard. IP `81.200.23.210` не блокируется — проблема в HTTP-клиенте: | Клиент | auth-api | deck-api-test | |---|---|---| | `curl` (без --http2) | ❌ 403 | ❌ 403 | | `curl --http2` | ✅ 200 | ❌ 403 | | `Node.js https` | ✅ 200 | ✅ 200 | | Браузер | ✅ 200 | ✅ 200 | **Правило для curl:** `--http2` + `Accept: application/json`. **Node.js (приложение):** работает без проблем. **Статус:** 🟢 подтверждено --- ## 4. Инфраструктура и деплой - **Платформа:** 🔴 уточнить - **CI/CD:** 🔴 уточнить - **Сетевое ограничение /export:** 🔴 уточнить --- ## 5. Функциональные уточнения ### 5.1. Мульти-компания в UI - Список компаний из `profiles[]`, активная по `is_active_profile` - Переключение: UI → `POST /switch-profile` на IAM → обновить сессию - **Статус:** 🟡 требует реализации ### 5.2. Soft-delete фильтр - `includeDeleted` всегда `false` - **Статус:** 🟡 не реализовано ### 5.3. Индивидуальные лимиты - **Статус:** 🔴 проверить ### 5.4. Уведомление о нормализации - **Статус:** 🔴 проверить --- ## 6. Тестовые данные | Email | ClientID | Компания | Роль | |---|---|---|---| | `tazetdinovn@gmail.com` | WZ03709 | naeel_test | Пользователь | | `client@example.com` | WZ01325 | Тест | Клиент | | `admin@nubes.ru` | WZ01112 | Нубес | Админ | ### HAR-сессия - Файл: `Files/nubes_login.har`, пользователь `tazet@narod.ru`, deck-test --- ## 7. Принятые решения | Дата | Решение | |---|---| | 01.06.2026 | Экспорт: txt, одна строка = один CIDR | | 01.06.2026 | Демо одобрено | | 02.06.2026 | Любой юзер компании редактирует whitelist всей компании | | 04.06.2026 | **IAM API — источник компаний.** `GET /auth/user` → `profiles[]`. `isAdmin` из `userInfo.isAdmin`. Переключение через `POST /switch-profile`. | | 04.06.2026 | ddos-guard: curl требует `--http2`, Node.js работает | | 16.06.2026 | **UI: кнопка Показать/Скрыть удалённые.** Вместо чекбокса — кнопка-переключатель. | | 16.06.2026 | **UI: восстановление удалённых записей.** Кнопка ↺ у удалённых, `POST /restore/:id`. Лимит проверяется. Аудит: RESTORE. | | 16.06.2026 | **UI: время МСК.** `toLocaleString('ru', {timeZone:'Europe/Moscow'})` + метка «МСК». | --- ## Легенда статусов | 🔴 | Требует уточнения | | 🟡 | Уточнено, не реализовано | | 🟢 | Реализовано / подтверждено | | ⚫ | Отменено / не актуально |