docs: актуализация (2026-05-30)

Deprecated (описывали состояние до рефакторинга):
  [DEPRECATED]-plan.md
  [DEPRECATED]-analysis-2026-05-30.md
  [DEPRECATED]-auth-architecture.md

Новые/обновлённые:
  architecture.md  — текущее устройство: стек, модули, auth-схема, env, маршруты
  plan.md          — только pending задачи (блокеры KK, деплой, Redis, пагинация)
  questions.md     — закрытые вопросы отмечены, открытые: KK creds + admin claim + /export IP
This commit is contained in:
“Naeel”
2026-05-30 14:42:52 +03:00
parent 9ad7eb9a8d
commit 608560eb64
7 changed files with 420 additions and 129 deletions
+41 -51
View File
@@ -1,80 +1,70 @@
# Вопросы для уточнения — IP WhiteList
# Вопросы к DevOps / команде Keycloak — IP WhiteList
> Дата: 2026-05-30
> Кому: команда Keycloak / Nubes
> Статус: ждём ответов
> Обновлено: 2026-05-30
> Часть вопросов из первоначального списка закрыта реализацией.
---
## 1. Admin-роль: «отдельный чек-бокс»
## ❌ ОТКРЫТЫЕ (блокируют деплой)
**ТЗ:** Администратор = `clientId = WZ01112` + отдельный чек-бокс.
### 1. Данные клиента Keycloak
**Вопросы:**
- В каком claim приходит этот чек-бокс? (realm_role, client_role, group, attribute?)
- Как точно называется claim? Примеры возможных значений:
- `"roles": ["whitelist-admin"]`
- `"resource_access.whitelist.roles": ["admin"]`
- `"is_admin": true`
- Нужна ли поддержка нескольких админов (не только WZ01112)?
Для активации OIDC-режима (код готов, ждёт переменных):
**Как обойти:** захардкодить `clientId === 'WZ01112'` как признак админа, добавить `TODO` с ссылкой на этот файл.
```
KC_CLIENT_ID= ? # наш client_id в realm cloud
KC_CLIENT_SECRET= ? # наш client_secret
```
Redirect URI для регистрации в Keycloak:
```
https://white.nodejsk8s.dev.nubes.ru/callback
```
---
## 2. Multi-company: формат claims
### 2. Admin-роль: как приходит из Keycloak
**ТЗ:** Пользователь может принадлежать нескольким компаниям, в UI — переключатель.
**ТЗ:** Администратор = `clientId = WZ01112` + «отдельный чек-бокс».
**Вопросы:**
- `clientID` в токене — это строка или массив строк?
- Если массив — как называется claim? (`clientIDs`, `groups`, что-то ещё?)
- Есть ли claim с названием компании (для отображения в переключателе)?
- Пример реального payload токена (без секретов) для пользователя с 2+ компаниями.
Сейчас: `isAdmin = (ClientID === process.env.ADMIN_CLIENT_ID)` — только WZ01112.
**Как обойти:** всегда считать `clientId` строкой (один клиент), переключатель не делать, добавить `TODO`.
Вопросы:
- Есть ли отдельный claim в JWT для признака admin?
- Если да — как называется? Примеры: `realm_access.roles`, `resource_access.whitelist.roles`, `is_admin`, `groups`…
- Нужна поддержка нескольких adminов или только WZ01112?
**Если нет отдельного claim** — оставляем текущее решение, закрываем вопрос.
---
## 3. IP-ограничение /export
### 3. /export — IP-ограничение
**ТЗ:** Endpoint экспорта «на старте может работать без авторизации (по сетевому ограничению)».
ТЗ: «на старте может работать без авторизации (по сетевому ограничению)».
**Вопросы:**
- Ограничение делаем в приложении или на уровне ingress (nginx/traefik)?
- Если в приложении — где взять список разрешённых IP? (env var, файл, БД?)
- Если ingress — кто настраивает?
Сейчас: открытый endpoint, rate-limit 20 req/мин.
**Как обойти:** оставить `/export` открытым, добавить `TODO`.
- Ограничение делаем в **приложении** или в **ingress/nginx**?
- Если в приложении — список разрешённых IP (env var `EXPORT_ALLOWED_IPS`?).
---
## 4. Email пользователя
## ✅ ЗАКРЫТЫЕ
**ТЗ:** `email` — идентификация пользователя для аудита.
**Вопросы:**
- Как называется claim с email? (`email`, `preferred_username`, что-то ещё?)
- Всегда ли он присутствует в токене?
**Как обойти:** брать `payload.email` с fallback на `payload.sub`, добавить `TODO`.
---
## 5. DEV_MODE
**Вопросы:**
- Нужен ли dev-режим на платформе Nubes (не локально)?
- Или всегда только реальный Keycloak?
**Как обойти:** оставить `DEV_MODE=true` с проверкой что в production падает при включении.
| # | Вопрос | Решение |
|---|---|---|
| DEV_MODE | Нужен ли dev-режим на платформе? | `/dev-login` — backdoor с `DEV_MODE=true` (без пароля) или `DEV_SECRET=xyz` (с ключом). Работает в обоих режимах. |
| Email claim | Как называется claim с email? | Берём `payload.email \|\| payload.login \|\| 'unknown'` |
| JWT структура | Формат токена auth-api | Изучен из реального токена (см. [DEPRECATED]-auth-architecture.md). Поля: `ClientID`, `company_id`, `company_name`, `email`, `login`. |
| CSRF | Защита POST-форм | csrf-csrf (double-submit cookie pattern) |
| Session | Хранение пользователя | express-session (httpOnly, sameSite lax, 8ч) |
---
## Условные обозначения в коде
```js
// TODO(KK): уточнить формат claim — см. docs/questions.md#2
// FIXME(KK): временно, заменить после ответа команды
```
// TODO(Keycloak): уточнить формат claim — см. docs/questions.md#1
// FIXME(Keycloak): временно, заменить после ответа команды
// HACK(DEV_MODE): заглушка, убрать перед продакшеном
```