docs: полностью переписан план Gemini на основе фактического кодобазы и ТЗ
This commit is contained in:
+40
-71
@@ -1,86 +1,55 @@
|
||||
# План разработки — IP WhiteList Microservice
|
||||
# Актуальный план разработки — IP WhiteList Microservice
|
||||
|
||||
> **Автор:** GitHub Copilot (Gemini 3.1 Pro Preview)
|
||||
> **Дата:** 2026-05-29
|
||||
> **Дата:** 2026-05-30
|
||||
> **Основание:** ТЗ (WhiteIPlist.txt) + Реальный код (Node.js/Express)
|
||||
|
||||
---
|
||||
## 1. Анализ предыдущего плана и моё мнение
|
||||
|
||||
## 1. Анализ предыдущих планов и моё видение
|
||||
Мой предыдущий план (`plan-gemini.md`) оказался **полностью оторванным от реальности**. Я предполагал писать всё с нуля на Python/FastAPI+SQLModel. На деле же ядро полностью готово и написано на **Node.js, Express, EJS и чистом SQL (pg pool)**.
|
||||
Писать с нуля на питоне — это плодить техдолг и выкидывать рабочий код. Более того, серверная валидация, структура БД, CRUD и UI уже в целом соответствуют ТЗ, но сильно не хватает связующих звеньев.
|
||||
|
||||
Я изучил ТЗ и варианты коллег (DeepSeek, Claude, GPT-5.4).
|
||||
- **DeepSeek** предложил избыточный Async/ORM подход.
|
||||
- **Claude** упростил до psycopg2 и HTMX, но оставил много "белых пятен" в работе с Keycloak.
|
||||
- **GPT-5.4** дал отличный продуктовый разбор рисков (гонки, лимиты, нормализация), но оставил проект заблокированным до "уточнения с командой Keycloak".
|
||||
Поэтому мой главный тезис: **хватит придумывать архитектуру, нужно закрывать дыры по функциональным требованиям ТЗ в текущем Node.js проекте.**
|
||||
|
||||
**Мой подход (Gemini 3.1 Pro):**
|
||||
Мы не будем блокировать разработку в ожидании ответов от админов Keycloak. Разночтения с форматами claims (как выглядит админ, как выглядит мульти-аккаунт) мы вынесем в **гибкую конфигурацию (.env)**. Если формат токена изменится, нам не придется править код, мы просто поменяем переменные окружения.
|
||||
Также мы откажемся от сторонней библиотеки `netaddr`, так как встроенный модуль Python `ipaddress` имеет встроенную функцию `collapse_addresses()`, которая идеально решает задачу агрегации по ТЗ.
|
||||
## 2. Разрыв между ТЗ (WhiteIPlist.txt) и кодом (Node.js)
|
||||
|
||||
---
|
||||
Что готово и работает:
|
||||
- **База данных:** Полная структура (`companies`, `whitelist_entries`, `audit_log`), реализован soft delete (`deleted_at`).
|
||||
- **Слой данных (`queries.js`):** Работает базовый CRUD, сохраняются логи аудита, обрабатываются ограничения (глобальные и кастомные).
|
||||
- **Валидация (`validators.js`):** Реализованы проверки на IPv4, маски /22-/32, зашиты все запрещённые диапазоны (RFC1918, CGNAT, Loopback и т.д.).
|
||||
- **UI:** Причесанный EJS-шаблон добавления/просмотра/удаления.
|
||||
|
||||
## 2. Технологический стек
|
||||
Чего не хватает по ТЗ (Фокус дальнейшей разработки):
|
||||
1. **Авторизация (Keycloak OIDC):** Сейчас сделан временный парсинг JWT через Base64 без валидации ключей (DEV_MODE).
|
||||
2. **Multi-company и Роли (Админ/Клиент):** Не реализованы переключатель компаний и админские страницы (видимость всех записей, изменение лимитов, просмотр аудита).
|
||||
3. **Редактирование записей:** Метод `updateEntry` написан в БД-слое, но UI и роут отсутствуют. Формально ТЗ не закрыто.
|
||||
4. **Агрегация в Экспорте:** Маршрут `GET /export` просто выплёвывает адреса в столбик, тогда как ТЗ жёстко требует суммаризировать подсети в минимальный набор CIDR.
|
||||
5. **Клиентская валидация:** ТЗ явно требует валидировать формат и маски на фронтенде перед отправкой.
|
||||
|
||||
* **Бэкенд:** FastAPI (Python 3.11+). Обеспечивает Pydantic-валидацию (используем встроенный `IPv4Network`).
|
||||
* **СУБД:** PostgreSQL.
|
||||
* **Доступ к данным:** SQLModel (надстройка над SQLAlchemy). Дает удобство ORM без избыточной сложности, синхронный режим.
|
||||
* **Суммаризация (Агрегация):** Standard Library Python `ipaddress.collapse_addresses`.
|
||||
* **Фронтенд:** Jinja2 + HTMX + TailwindCSS (через CDN или standalone cli для простоты).
|
||||
* **Авторизация:** Dependency injection в FastAPI для OIDC/JWT. Заглушка (MockOIDC) для локальной разработки.
|
||||
## 3. Детальный план по шагам (Node.js)
|
||||
|
||||
---
|
||||
### Этап 1: Исправление багов в текущем MVP
|
||||
- [ ] **Баг с overlaps:** В `validators.js` функция `overlaps()` содержит логическую ошибку в `start`/`end` (может пропускать пересекающиеся подсети). Переписать условие.
|
||||
- [ ] **UI Редактирования:** Добавить роут `POST /update/:id` в `server.js` и добавить кнопку/форму "Изменить" в `index.ejs`, подключив существующую `updateEntry(...)`.
|
||||
|
||||
## 3. Решение узких мест (Архитектурные решения)
|
||||
### Этап 2: Строгое соответствие ТЗ (Валидация и Экспорт)
|
||||
- [ ] **Суммаризация CIDR:** Так как в Node.js нет `ipaddress.collapse_addresses`, необходимо использовать библиотеку вроде `cidr-tools` (функция `merge()` отлично справится) для `GET /export`.
|
||||
- [ ] **Клиентская валидация:** Добавить минимальный JavaScript в `index.ejs` для проверки валидности вводимого IP-адреса и маски до ухода POST-запроса, чтобы экономить серверные ресурсы (Требование ТЗ).
|
||||
|
||||
**Проблема 1: Как определять администратора и принадлежность к компаниям из токена?**
|
||||
*Решение:* Выносим структуру токена в `Config`.
|
||||
```env
|
||||
OIDC_COMPANY_CLAIM="client_id" # Может быть списком или строкой, обработаем оба варианта
|
||||
OIDC_ADMIN_CLAIM_KEY="roles"
|
||||
OIDC_ADMIN_CLAIM_VALUE="whitelist-admin"
|
||||
```
|
||||
Код будет динамически проверять, совпали ли значения, указанные в конфиге, с данными из токена.
|
||||
### Этап 3: Подключение OIDC Keycloak
|
||||
- [ ] Установка библиотеки `openid-client` (или `passport-openidconnect`).
|
||||
- [ ] Настройка middleware: получение сертификатов из Keycloak, валидация подписи JWT-токена.
|
||||
- [ ] Извлечение claim `clientID` (и логика переключения между компаниями, если `clientID` является массивом). Определение роли (кто админ, `WZ01112`). Обязательный отказ от dev-заглушки в PROD.
|
||||
|
||||
**Проблема 2: Гонки при записи и лимиты**
|
||||
*Решение:*
|
||||
1. Проверка лимита делается запросом `SELECT count(*) FROM entries WHERE company_id = X AND deleted_at IS NULL FOR UPDATE`. Блокировка на чтение защитит транзакцию от гонок.
|
||||
2. В БД создадим уникальный индекс `CREATE UNIQUE INDEX unique_active_cidr ON entries (company_id, value_cidr) WHERE deleted_at IS NULL;` для защиты от дубликатов на уровне СУБД.
|
||||
### Этап 4: Админ-панель (пользователь WZ01112)
|
||||
- [ ] Роут `GET /admin` и шаблон `admin.ejs`. Таблица со всеми компаниями и их лимитами, фильтрацией.
|
||||
- [ ] Функционал установки `custom_limit` для компании.
|
||||
- [ ] Страница/вкладка `GET /admin/audit` для просмотра `audit_log`.
|
||||
- [ ] Переключатель отображения Soft-deleted записей.
|
||||
|
||||
**Проблема 3: Пересечения внутри компании**
|
||||
*Решение:* Перед INSERT/UPDATE выгружаем все активные подсети компании и проверяем через `new_cidr.overlaps(existing_cidr)`. Выгрузка делается в рамках заблокированной транзакции (см. пункт выше).
|
||||
## 4. Зависимости
|
||||
В `package.json` придется добавить лишь две новые production-зависимости, не усложняя проект:
|
||||
- `cidr-tools` (для агрегации при экспорте)
|
||||
- `openid-client` / `jsonwebtoken` (для безопасной работы с Keycloak)
|
||||
|
||||
---
|
||||
|
||||
## 4. Поэтапный план реализации
|
||||
|
||||
### Этап 1. Ядро и База данных (Бизнес-логика)
|
||||
- [ ] Инициализация FastAPI проекта, настройка SQLModel.
|
||||
- [ ] Определение сущностей БД: `Company`, `WhitelistEntry` (CIDR хранится как `String`, но Pydantic проверяет `IPv4Network`), `AuditLog`.
|
||||
- [ ] Валидаторы (запрещенные списки Приложения А, маска /32 - /22). Нормализация `strict=False` в `ipaddress`, чтобы `192.168.1.5/24` автоматически перегонялось в `192.168.1.0/24`.
|
||||
- [ ] Написание Unit-тестов для валидаторов.
|
||||
|
||||
### Этап 2. Слой данных (CRUD) и защита от гонок
|
||||
- [ ] Сервис создания записи: проверка макс. лимита (15 по умолчанию или `company.custom_limit`), поиск пересечений, запись AuditLog.
|
||||
- [ ] Сервис Soft-Delete и редактирования.
|
||||
- [ ] Тесты CRUD-сервисов.
|
||||
|
||||
### Этап 3. Авторизация (Keycloak)
|
||||
- [ ] Настройка `auth/jwt.py` для валидации RS256 подписей.
|
||||
- [ ] Парсинг токена на основе гибких правил из `.env` (роли, список компаний).
|
||||
- [ ] FastAPI Security Depends (`get_current_user`).
|
||||
|
||||
### Этап 4. Внешний API (Export Endpoint)
|
||||
- [ ] Роут `GET /api/v1/export/whitelist.txt`.
|
||||
- [ ] Выборка всех `value_cidr` где `deleted_at IS NULL`.
|
||||
- [ ] Агрегация: `[str(net) for net in ipaddress.collapse_addresses(net_list)]`.
|
||||
- [ ] Middleware для ограничения доступа по списку разрешенных `EXPORT_ALLOWED_IPS`.
|
||||
|
||||
### Этап 5. Пользовательский Интерфейс (UI)
|
||||
- [ ] Jinja2 шаблоны и использование HTMX для добавления/удаления строк таблицы без перезагрузки всей страницы.
|
||||
- [ ] Отображение предупреждений (нормализация, превышение лимита).
|
||||
- [ ] Селектор активной компании.
|
||||
- [ ] Панель администратора (все компании, настройка `custom_limit`, просмотр аудита).
|
||||
|
||||
### Этап 6. Инфраструктура
|
||||
- [ ] Dockerfile.
|
||||
- [ ] docker-compose окружение (App + Postgres).
|
||||
- [ ] Документация (README с описанием переменных окружения).
|
||||
Всё остальное будет реализовано в рамках существующего стека.
|
||||
|
||||
Reference in New Issue
Block a user