Files
IPWhiteList/docs/[DEPRECATED]-plan-gpt54.md
T

27 KiB
Raw Blame History

Актуальный план реализации — IP WhiteList

Автор: GitHub Copilot (GPT-5.4) Дата: 2026-05-30 Основание: ТЗ из WhiteIPlist.txt + фактический код в ipwhitelist-app Статус: заменяет предыдущую версию плана

1. Вывод по текущему состоянию

Предыдущий план был неполным, потому что строился не от ТЗ, а от видимого MVP. После сверки с WhiteIPlist.txt картина такая:

  1. Основа сервиса уже написана лучше, чем казалось: схема БД, soft delete, аудит, custom_limit, updateEntry и полный список запрещённых диапазонов уже есть в коде.
  2. Основной разрыв находится не в модели данных, а между слоями: часть функций реализована в src/queries.js, но не выведена в server.js и views.
  3. Главные недостающие вещи для соответствия ТЗ: нормальная OIDC-авторизация, admin-сценарии, редактирование из UI, клиентская валидация, агрегирующий экспорт.
  4. Переписывать стек или БД не нужно. Нужно довести существующую реализацию до полноты требований.

2. Что требует ТЗ

Сервис по ТЗ обязан поддерживать:

  1. Self-service страницу управления whitelist-записями.
  2. Авторизацию через Keycloak OIDC.
  3. Роли client и admin.
  4. Возможность работы пользователя с одной или несколькими компаниями.
  5. Создание, редактирование и soft delete записей.
  6. Серверную и клиентскую валидацию IPv4/CIDR.
  7. Глобальный лимит и индивидуальные лимиты по компаниям.
  8. Журнал аудита.
  9. Внешний endpoint выдачи агрегированного списка активных CIDR.
  10. Admin-функции: просмотр всех компаний, фильтрация, просмотр удалённых записей, изменение лимитов.

3. Что уже реализовано сейчас

3.1 База данных

В sql/schema.sql уже есть всё базовое, что нужно для ТЗ:

  1. Таблица companies с client_id и custom_limit.
  2. Таблица whitelist_entries с updated_by, updated_at, deleted_by, deleted_at.
  3. Таблица audit_log.
  4. Индекс активных записей и индекс по audit_log(company_id).

Вывод: схему БД переписывать не нужно.

3.2 Серверная логика

В src/queries.js уже реализованы:

  1. getOrCreateCompany
  2. getLimit
  3. listEntries с includeDeleted
  4. createEntry
  5. updateEntry
  6. deleteEntry как soft delete
  7. getExportCIDRs
  8. getAudit

Вывод: слой работы с БД уже покрывает значительную часть ТЗ.

3.3 Валидация

В src/validators.js уже есть:

  1. Только IPv4.
  2. Маски только /22–/32.
  3. Нормализация host-битов.
  4. Запрет всех диапазонов из Приложения А ТЗ, включая CGNAT, Benchmarking, Multicast, Reserved и Limited broadcast.
  5. Проверка пересечений.

Вывод: серверная валидация по составу требований почти полная.

3.4 UI и маршруты

В server.js и views/index.ejs уже есть:

  1. Главная страница со списком записей.
  2. Форма добавления.
  3. Soft delete через POST /delete/:id.
  4. Экспорт через GET /export.
  5. Вывод текущего лимита и числа использованных записей.
  6. UI, близкий к стилю Nubes.

Вывод: клиентский сценарий создания и удаления уже работает как MVP.

4. Что не соответствует ТЗ или не доведено до конца

4.1 Авторизация

Сейчас в server.js не OIDC, а упрощённый decode токена через base64 без проверки подписи. Это подходит только как временная заглушка, но не соответствует ТЗ.

Нужно:

  1. Реальная проверка JWT через Keycloak/JWKS или openid-client.
  2. Нормальный маппинг claims в user-модель.
  3. Явное определение роли admin.
  4. Поддержка сценария с несколькими компаниями.

Это главный блокер продакшна.

4.2 Редактирование записи

updateEntry уже написана, но:

  1. Нет роута POST /update/:id.
  2. Нет формы редактирования в index.ejs.
  3. Нет пользовательского сценария изменения записи.

То есть требование ТЗ формально не закрыто, хотя код на уровне queries уже есть.

4.3 Admin-функции

По ТЗ администратор должен:

  1. Видеть записи всех компаний.
  2. Фильтровать по компании.
  3. Видеть soft-deleted записи.
  4. Смотреть аудит.
  5. Менять лимиты компаний.

Сейчас ничего из этого не выведено в server.js и views.

4.4 Экспорт

GET /export уже есть, но он отдаёт просто список value_cidr без агрегации. ТЗ требует суммаризацию в минимальный набор CIDR по всем активным записям.

Это функциональный разрыв, а не косметика.

4.5 Клиентская валидация

ТЗ требует валидацию на клиенте и сервере. Сейчас есть только серверная.

Нужно добавить в форму как минимум:

  1. Проверку формата IPv4/CIDR.
  2. Проверку диапазона маски.
  3. Ограничение длины комментария.
  4. Сообщение о возможной нормализации.

4.6 Multi-company сценарий

ТЗ явно говорит, что пользователь может принадлежать нескольким компаниям. Сейчас всё построено вокруг одного clientId в req.user.

Нужно:

  1. Понять реальный формат claims.
  2. Ввести activeCompany в контекст пользователя.
  3. Добавить переключатель активной компании в UI.

5. Что не надо перепридумывать

  1. Не надо переписывать проект на другой язык или другой фреймворк.
  2. Не надо менять схему БД ради самой схемы.
  3. Не надо переписывать validators.js целиком.
  4. Не надо переписывать queries.js целиком.
  5. Не надо делать SPA.

Правильный путь: минимально нарастить уже существующую Node.js/Express/EJS реализацию.

6. Риски и спорные места

6.1 overlaps в validators.js

Условие в overlaps написано нестандартно и плохо читается. Прямого доказанного бага по одной только формуле сейчас нет, но это место требует отдельного теста на:

  1. полное совпадение,
  2. вложенность,
  3. непересекающиеся диапазоны,
  4. соседние диапазоны,
  5. одиночный IP против подсети.

Решение: сначала добавить точечные тесты, и только потом менять формулу, если тест покажет дефект.

6.2 Admin-роль

ТЗ говорит: admin это clientId = WZ01112 и отдельный чек-бокс. Сейчас неясно, как этот чек-бокс попадает в токен. Без этого нельзя финально закрыть auth-модель.

6.3 Multi-company claims

ТЗ требует сценарий нескольких компаний, но в списке claims указан только clientID. Здесь нужна конкретика от команды Keycloak.

7. Новый план реализации

Этап 1. Довести до полноты пользовательский сценарий

Цель: закрыть основной client-flow без смены архитектуры.

  1. Добавить роут POST /update/:id в server.js.
  2. Добавить UI редактирования в views/index.ejs.
  3. Показать updated_at и updated_by, если запись менялась.
  4. Добавить клиентскую валидацию формы добавления и редактирования.
  5. Добавить точечные тесты на overlaps и нормализацию.

Результат этапа: client сможет не только добавлять и удалять, но и редактировать записи, как требует ТЗ.

Этап 2. Закрыть admin-функциональность

Цель: реализовать недостающую управленческую часть ТЗ.

  1. Ввести определение роли admin в auth-слое.
  2. Добавить GET /admin.
  3. Добавить фильтр по компании.
  4. Добавить показ удалённых записей.
  5. Добавить GET /admin/audit.
  6. Добавить POST /admin/limit/:companyId.
  7. Добавить отдельный admin view.

Результат этапа: появляется реальная административная панель, а не только клиентский экран.

Этап 3. Привести авторизацию к ТЗ

Цель: убрать временную заглушку и сделать реальную интеграцию с Keycloak.

  1. Заменить наивный decode токена на верификацию подписи.
  2. Добавить конфигурацию issuer, audience, jwks/oidc.
  3. Нормализовать claims в req.user.
  4. Поддержать admin-claim.
  5. Поддержать multi-company claims.
  6. Оставить DEV_MODE только для локальной разработки.

Результат этапа: сервис можно выводить из чисто dev-сценария.

Этап 4. Довести экспорт до требований ТЗ

Цель: сделать экспорт пригодным для систем фильтрации.

  1. Добавить суммаризацию активных записей в минимальный набор CIDR.
  2. Суммаризировать по всем компаниям совместно.
  3. Исключать soft-deleted записи.
  4. Оставить выдачу text/plain, одна строка на объект.
  5. Отдельно решить, где ограничивается доступ к export endpoint: ingress, app или оба уровня.

Результат этапа: экспорт соответствует ТЗ, а не является просто дампом таблицы.

Этап 5. Завершение и проверка полноты

  1. Сверить все пункты ТЗ с реализованным поведением.
  2. Обновить тестовый сценарий.
  3. Проверить UX ошибок и предупреждений.
  4. Проверить поведение при снижении custom_limit ниже текущего числа активных записей.
  5. Проверить сценарии admin/client отдельно.

8. Практический приоритет

Если делать не всё сразу, а по реальной важности, порядок такой:

  1. Редактирование записи из UI.
  2. Клиентская валидация.
  3. Admin-панель и лимиты.
  4. Реальный OIDC.
  5. Multi-company.
  6. Суммаризация export.

Почему именно так:

  1. Редактирование уже почти готово и закрывает явный пробел ТЗ.
  2. Admin-функции сейчас отсутствуют полностью.
  3. OIDC блокирует продакшн, но не мешает локально добить функциональность.
  4. Экспорт уже работает как черновой endpoint, но должен быть доведён до суммаризации до релиза.

9. Итог

Правильный план для этого проекта не “переписать всё правильно”, а “довести уже написанное до требований ТЗ”.

Текущее состояние проекта:

  1. Data-layer в основном готов.
  2. Server-layer частично готов.
  3. UI-layer закрывает только часть client-сценария.
  4. Auth-layer пока временный.
  5. Admin-layer почти отсутствует.
  6. Export-layer не завершён по требованиям агрегации.

Главный вывод: проект ближе к рабочему состоянию, чем казалось по старым планам, но прошлый план был методологически неверен, потому что не опирался на ТЗ и не различал “не написано” и “написано, но не подключено”.

Эта часть критична. Её нужно делать одной из первых и сразу покрывать тестами.

Поддерживаемый ввод

  1. Одиночный IPv4 адрес, который трактуется как /32.
  2. IPv4 подсеть в CIDR нотации.

Запрещённый ввод

  1. IPv6.
  2. Доменное имя.
  3. Маска шире допустимой.
  4. Любые private или special ranges из приложения А.

Правила маски

Допустимы только /22 ... /32.

Нормализация

Если пользователь ввёл адрес с host-битами, сервис должен:

  1. Нормализовать значение до адреса сети.
  2. Сохранить нормализованное значение.
  3. Вернуть пользователю явное сообщение, что адрес был нормализован.

Проверки в пределах компании

  1. Запрет полного дубликата активной записи.
  2. Запрет любого пересечения активной записи с существующими активными записями той же компании.
  3. Между разными компаниями пересечения допускаются.

Список запрещённых диапазонов

Нужно захардкодить как конфигурацию приложения и покрыть тестами:

  1. 10.0.0.0/8
  2. 172.16.0.0/12
  3. 192.168.0.0/16
  4. 100.64.0.0/10
  5. 127.0.0.0/8
  6. 169.254.0.0/16
  7. 192.0.0.0/24
  8. 192.0.2.0/24
  9. 198.51.100.0/24
  10. 203.0.113.0/24
  11. 198.18.0.0/15
  12. 224.0.0.0/4
  13. 240.0.0.0/4
  14. 255.255.255.255/32

10. Лимиты и конкурентность

Это важное место, которого обычно недооценивают.

Правила лимитов

  1. Есть глобальный DEFAULT_LIMIT, по умолчанию 15.
  2. Для компании может быть custom_limit.
  3. При снижении лимита ниже текущего количества записей существующие записи не удаляются.
  4. Пока число активных записей больше лимита, новые записи создавать нельзя.

Риск гонок

Если два запроса одновременно создают записи в одной компании, возможны:

  1. Пробитие лимита.
  2. Пропуск пересечения.
  3. Пропуск дубликата.

Что делать

Операцию создания и обновления записи нужно делать в транзакции с сериализацией логики на уровне компании. Практически это можно решить так:

  1. Брать advisory lock по company_id перед проверками и записью.
  2. Либо делать SELECT ... FOR UPDATE по строке компании, если этого достаточно для вашей схемы доступа.

Для первой версии я бы выбрал advisory lock по company_id. Это проще и надёжнее для бизнес-ограничений, которые нельзя полностью выразить обычным unique index.

11. Экспорт агрегированного списка

Требования

  1. В экспорт попадают только активные записи.
  2. Данные берутся по всем компаниям.
  3. Пересечения между компаниями допустимы на уровне хранения, но в export должны агрегироваться в минимальный набор CIDR.
  4. Формат ответа: text/plain.
  5. Одна строка = один CIDR.

Что нужно зафиксировать реализационно

  1. Результат должен быть отсортирован для стабильности.
  2. В ответе должен быть завершающий перевод строки.
  3. Content-Type должен быть text/plain; charset=utf-8.
  4. Желательно отдавать Content-Disposition с понятным именем файла.

Защита endpoint

Если endpoint на старте работает без auth, то доступ надо ограничить минимум одним из способов:

  1. Проверка client IP в приложении.
  2. Ограничение на reverse proxy.
  3. Оба сразу.

12. UI-потоки

Экран клиента

Должны быть:

  1. Селектор активной компании, если компаний несколько.
  2. Таблица записей.
  3. Индикатор использовано X из N.
  4. Форма создания записи.
  5. Возможность редактирования.
  6. Возможность soft delete.

Экран администратора

Должны быть:

  1. Таблица по всем компаниям.
  2. Фильтр по компании.
  3. Фильтр показа удалённых записей.
  4. Просмотр журнала аудита.
  5. Управление лимитами компании.

UX-детали, которые обязательно сделать

  1. Понятные сообщения об ошибках валидации.
  2. Явное сообщение о нормализации адреса.
  3. Явное сообщение о превышении лимита.
  4. Явное сообщение о пересечении с существующей записью.

13. Пошаговый план реализации

Этап 1. Каркас проекта

  1. Создать структуру каталогов.
  2. Подготовить requirements.txt.
  3. Подготовить .env.example.
  4. Подключить FastAPI, Jinja2, static.
  5. Подготовить docker-compose.yml с PostgreSQL.

Результат этапа: приложение стартует, открывается базовая страница, есть подключение к БД.

Этап 2. Схема БД и миграции

  1. Настроить Alembic.
  2. Создать initial migration.
  3. Поднять таблицы companies, whitelist_entries, audit_log.
  4. Добавить нужные индексы.

Результат этапа: схема БД фиксирована и воспроизводима.

Этап 3. Валидатор CIDR

  1. Реализовать разбор IPv4 и CIDR.
  2. Реализовать проверку маски.
  3. Реализовать нормализацию.
  4. Реализовать проверку запрещённых диапазонов.
  5. Написать тесты на валидатор.

Результат этапа: независимый, протестированный модуль бизнес-валидации.

Этап 4. Сервисный слой для записей

  1. Реализовать list.
  2. Реализовать create.
  3. Реализовать update.
  4. Реализовать soft delete.
  5. Реализовать проверки лимитов, дубликатов и пересечений.
  6. Добавить транзакционную защиту от гонок.

Результат этапа: бизнес-операции работают без UI.

Этап 5. Аудит

  1. Добавить запись CREATE.
  2. Добавить запись UPDATE со старым и новым состоянием.
  3. Добавить запись DELETE.
  4. Добавить интерфейс чтения для admin.

Результат этапа: все изменяющие действия фиксируются.

Этап 6. Авторизация

  1. Реализовать dev-заглушку.
  2. Реализовать чтение и валидацию JWT из Keycloak.
  3. Реализовать преобразование claims в current user.
  4. Реализовать проверки client/admin.
  5. Реализовать переключение компании.

Результат этапа: права и контекст пользователя работают сквозным образом.

Этап 7. HTML-интерфейс

  1. Реализовать страницу списка.
  2. Реализовать формы создания и редактирования.
  3. Реализовать soft delete из UI.
  4. Реализовать админские экраны.

Результат этапа: сервис пригоден для ручной эксплуатации.

Этап 8. Экспорт

  1. Реализовать сбор всех активных CIDR.
  2. Реализовать агрегацию.
  3. Реализовать endpoint export.
  4. Реализовать сетевое ограничение.

Результат этапа: внешняя система может забирать текстовый агрегированный whitelist.

Этап 9. Финализация

  1. Написать README.
  2. Подготовить Dockerfile.
  3. Подготовить пример systemd unit при необходимости.
  4. Прогнать ручной smoke-test.

Результат этапа: сервис можно разворачивать и передавать коллегам.

14. Тестовая стратегия

Минимально обязательные тесты:

  1. Валидный одиночный IPv4 превращается в /32.
  2. Валидная подсеть принимается.
  3. Host-биты нормализуются.
  4. Маски шире допустимой границы отклоняются.
  5. IPv6 отклоняется.
  6. Все запрещённые диапазоны отклоняются.
  7. Дубликат в одной компании запрещён.
  8. Пересечение в одной компании запрещено.
  9. Тот же CIDR в другой компании разрешён.
  10. Soft delete освобождает лимит.
  11. Export не включает soft-deleted записи.
  12. Export агрегирует CIDR корректно.
  13. Client не видит чужие компании.
  14. Admin видит все компании.
  15. Аудит создаётся для create, update, delete.

15. Что можно отложить после первой версии

Это не нужно тащить в MVP:

  1. Полноценный SPA.
  2. Сложная ORM.
  3. WebSocket.
  4. Фоновая очередь.
  5. Исторические версии записей кроме audit log.
  6. Автоматическое уведомление по email.

16. Главные риски проекта

  1. Неясный формат claims из Keycloak.
  2. Гонки при одновременном создании записей.
  3. Ошибки в трактовке пересечений CIDR.
  4. Неправильная нормализация адресов без понятного сообщения пользователю.
  5. Слишком раннее усложнение фронтенда.

17. Что я бы делал первым

Если начинать реализацию прямо сейчас, порядок такой:

  1. Каркас проекта.
  2. Схема БД.
  3. Валидатор и тесты.
  4. Сервис create/update/delete с транзакциями.
  5. Только потом UI и Keycloak.

Это самый безопасный путь: сначала фиксируется ядро бизнес-логики, потом уже внешний слой.

18. Итоговое решение

За основу реализации стоит брать простой Python/FastAPI сервис с PostgreSQL, синхронной серверной логикой, жёсткой серверной валидацией, транзакционной защитой от гонок и минималистичным HTML UI.

Главная мысль: сложность здесь не во фронтенде и не в фреймворке, а в корректной реализации правил CIDR, лимитов, ролей и аудита. План должен защищать именно эти части, а не раздувать стек.