# План разработки — IP WhiteList Microservice > **Автор:** GitHub Copilot (Gemini 3.1 Pro Preview) > **Дата:** 2026-05-29 --- ## 1. Анализ предыдущих планов и моё видение Я изучил ТЗ и варианты коллег (DeepSeek, Claude, GPT-5.4). - **DeepSeek** предложил избыточный Async/ORM подход. - **Claude** упростил до psycopg2 и HTMX, но оставил много "белых пятен" в работе с Keycloak. - **GPT-5.4** дал отличный продуктовый разбор рисков (гонки, лимиты, нормализация), но оставил проект заблокированным до "уточнения с командой Keycloak". **Мой подход (Gemini 3.1 Pro):** Мы не будем блокировать разработку в ожидании ответов от админов Keycloak. Разночтения с форматами claims (как выглядит админ, как выглядит мульти-аккаунт) мы вынесем в **гибкую конфигурацию (.env)**. Если формат токена изменится, нам не придется править код, мы просто поменяем переменные окружения. Также мы откажемся от сторонней библиотеки `netaddr`, так как встроенный модуль Python `ipaddress` имеет встроенную функцию `collapse_addresses()`, которая идеально решает задачу агрегации по ТЗ. --- ## 2. Технологический стек * **Бэкенд:** 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. Решение узких мест (Архитектурные решения) **Проблема 1: Как определять администратора и принадлежность к компаниям из токена?** *Решение:* Выносим структуру токена в `Config`. ```env OIDC_COMPANY_CLAIM="client_id" # Может быть списком или строкой, обработаем оба варианта OIDC_ADMIN_CLAIM_KEY="roles" OIDC_ADMIN_CLAIM_VALUE="whitelist-admin" ``` Код будет динамически проверять, совпали ли значения, указанные в конфиге, с данными из токена. **Проблема 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;` для защиты от дубликатов на уровне СУБД. **Проблема 3: Пересечения внутри компании** *Решение:* Перед INSERT/UPDATE выгружаем все активные подсети компании и проверяем через `new_cidr.overlaps(existing_cidr)`. Выгрузка делается в рамках заблокированной транзакции (см. пункт выше). --- ## 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 с описанием переменных окружения).