From dbb89c7b8423cacafcef0fe87f9b39aa81e307b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Fri, 29 May 2026 20:52:27 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D1=80=D0=B0=D0=B1=D0=BE=D1=87=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=BF=D0=BB=D0=B0=D0=BD=20=D1=81=20=D1=83=D1=87=D1=91?= =?UTF-8?q?=D1=82=D0=BE=D0=BC=20=D1=80=D0=B0=D0=B7=D0=B2=D0=B5=D0=B4=D0=BA?= =?UTF-8?q?=D0=B8=20(Node.js,=20lk-api-gateway)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plan-working.md | 103 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 docs/plan-working.md diff --git a/docs/plan-working.md b/docs/plan-working.md new file mode 100644 index 0000000..219b46b --- /dev/null +++ b/docs/plan-working.md @@ -0,0 +1,103 @@ +# Рабочий план — IP WhiteList + +> **Автор:** GitHub Copilot (Claude Sonnet 4.6) +> **Дата:** 2026-05-29 +> **Стек:** Node.js + Express + pg + EJS +> **Деплой:** nubes_nodejs + nubes_postgres (через веб-кабинет) + +--- + +## Что выяснили + +| Факт | Детали | +|---|---| +| **API шлюз** | `lk-api-gateway.ngcloud.ru`, за DDOS-Guard | +| **JWT** | `iss: auth-api`, claims: `ClientID`, `company_id`, `company_name`, `email` | +| **Токен для dev** | `secrets.txt`, tech-токен, долгий | +| **Валидация JWT** | Шлюз делает сам, нам не нужно | +| **Деплой** | Пользователь создаёт инстансы через веб-кабинет | +| **isAdmin** | ❓ В JWT нет, нужно уточнить как передавать | +| **Мульти-компании** | ❓ В JWT одна компания, список — в authData (localStorage) | + +--- + +## Файлы проекта (всё в корне) + +``` +├── server.js # Express: старт, роуты, middleware +├── db.js # pg Pool +├── .env.example # DB_DSN, PORT, DEFAULT_LIMIT, DEV_MODE +├── package.json +├── views/ # EJS-шаблоны +│ └── index.ejs # таблица + форма +├── public/ +│ └── style.css +├── sql/ +│ └── schema.sql # CREATE TABLE companies, whitelist_entries, audit_log +└── .gitignore +``` + +--- + +## Схема БД + +```sql +companies (id, client_id UNIQUE, name, custom_limit) +whitelist_entries (id, company_id FK, value_cidr, comment, created_by, created_at, updated_by, updated_at, deleted_by, deleted_at) +audit_log (id, user_email, company_id, action, old_value, new_value, created_at) +``` + +- `deleted_at IS NULL` = активная запись +- `custom_limit IS NULL` = использовать DEFAULT_LIMIT (15) + +--- + +## Порядок действий + +### Шаг 1 — Каркас +- package.json (express, pg, ejs, dotenv) +- server.js (Express, EJS, static, health check `/healthz`) +- db.js (pg Pool, `SELECT 1` при старте) +- .env.example + +### Шаг 2 — Схема БД +- sql/schema.sql +- Запустить на своём PG + +### Шаг 3 — Валидатор IPv4 +- Функция validateCIDR(input) → { cidr, wasNormalized } | error +- Правила: /32–/22, запрет серых, нормализация host-битов + +### Шаг 4 — CRUD (сырой pg, без ORM) +- Список записей компании +- Создание (проверка лимита, дубликатов, пересечений) +- Редактирование +- Soft-delete + +### Шаг 5 — Auth middleware +- DEV_MODE=true: читать заголовок X-Dev-User +- PROD: читать JWT из Authorization (шлюз уже проверил) + +### Шаг 6 — UI +- Таблица + форма создания/редактирования +- Индикатор лимита «X из N» +- Сообщения: нормализация, превышение, пересечение + +### Шаг 7 — Аудит +- Запись в audit_log при create/update/delete + +### Шаг 8 — Экспорт +- GET /api/v1/export — txt, все активные CIDR + +### Шаг 9 — Деплой +- Завести nubes_postgres и nubes_nodejs через кабинет +- Подключить к API-шлюзу (уточнить процедуру) + +--- + +## Что откладываем + +- Keycloak OIDC (шлюз делает) +- Полноценный админ-интерфейс +- Переключатель компаний (multi-profile) +- Тонкая настройка прав