Files
ipam_control/docs/changes/001-ipam-backend/PLAN.md
T
ayurishchevandClaude Sonnet 5 a846d30872 IPAM Manager: API, UI-админка, журнал аудита
Backend (FastAPI, SQLAlchemy 2, Alembic, PostgreSQL 16):
- организации, VRF, префиксы (дерево, использование, автоназначение),
  адреса, операторы связи, устройства и типы устройств; JWT, роли admin/viewer;
- VRF принадлежит организации (составной FK), смена VRF у префикса
  переносит поддерево, имя VRF уникально в организации;
- журнал аудита: поиск и фильтры, ротация (срок/количество), очистка
  по паролю с блокировкой, IP клиента и метаданные запроса
  (X-Forwarded-For только от TRUSTED_PROXIES).

UI (web/, без сборки): экраны и диалоги по макетам «IPAM Manager»,
кликабельные строки реестров, локальные шрифты IBM Plex,
собственные выпадающие списки.

Окружение: docker-compose (postgres + app), миграции Alembic 0001-0004,
scripts/gen_env.py, scripts/seed_demo.py, 11 автотестов (pytest).
Документация: README.md и docs/changes/001-005 (планы и итоги).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 12:27:47 +03:00

8.7 KiB
Raw Blame History

IPAM Manager — backend (Python + PostgreSQL) и UI-админка

Context

Есть макеты «IPAM Manager» (страница 2 канваса): Обзор, Префиксы (дерево, VRF), Адреса в подсети, Организации, Операторы связи, Устройства (+ типы), Журнал, диалоги создания/редактирования. Проект пуст. Нужно спроектировать и реализовать API-first приложение: backend на Python с PostgreSQL, UI-админка — отдельный лёгкий фронт (без сборки), который только визуализирует ответы API.

Решения (согласованы): FastAPI + SQLAlchemy 2 + Alembic + psycopg3; UI — статический SPA (Alpine.js + fetch), раздаётся тем же приложением; auth — локальные пользователи + JWT; окружение — Docker Compose (postgres + app), venv в корне для тестов/линтеров.

Доменная модель (PostgreSQL)

Нативные типы CIDR / INET — сравнения, вложенность (<<=, >>=) и семейство (family()) считает БД.

Таблица Ключевые поля
organizations name, short_name, inn (uniq), address, contact_person, phone, email, note
vrfs organization_id, name, route_target, note; uniq(org, name)
prefixes organization_id, vrf_id, prefix CIDR, description, status (active/reserved/deprecated), parent_id (авто по вложенности, можно задать), is_pool, note; uniq(vrf, prefix)
addresses prefix_id, address INET, status (assigned/reserved/deprecated), dns_name, description, device_id, note, updated_at; uniq(prefix, address); CHECK «адрес ∈ префикс» на уровне сервиса
isps name, organization_id, contract_number, hotline, note
isp_networks isp_id, cidr (несколько IP-блоков на оператора)
device_types name (uniq), is_default
devices name (hostname), device_type_id, mac, organization_id, note
users username (uniq), password_hash (argon2), role (admin/viewer), is_active
audit_log ts, user_id, entity_type, entity_id, entity_label, action (created/updated/deleted/assigned), diff JSONB

Вычисляемое (не хранится): использование префикса (назначено/ёмкость), «свободные» адреса (в макете статус «Свободен» — пропуски в диапазоне), число префиксов/адресов у организации, число устройств у типа, число IP у устройства. Правила: VRF/тип нельзя удалить, пока используются (в макете кнопка disabled) → 409.

API (/api/v1, OpenAPI на /docs)

  • auth: POST /auth/login, GET /auth/me (logout — на клиенте, токен короткоживущий).
  • overview: GET /overview — карточки (префиксов, VRF, адресов, использование, резерв), топ загрузки, последние изменения.
  • organizations, isps, devices, device-types, vrfs: CRUD; списки с q, limit, offset, фильтры (org, тип, vrf).
  • prefixes: CRUD; GET /prefixes?org=&vrf=&status=&family=&q= (дерево через parent_id + utilization); счётчики вкладок VRF; GET /prefixes/{id}.
  • prefixes/{id}/addresses: список (status, q, limit/offset — «Показать ещё 100»), POST назначить, POST .../next — автоназначение из пула (is_pool), сводка «назначено/резерв/свободно».
  • addresses/{id}: PATCH/DELETE.
  • audit: GET /audit (фильтры, пагинация) — источник «Последних изменений»; полный экран «Журнал» — вне этого этапа.
  • Единый формат ошибок {code, message, fields}; валидация CIDR/IP/MAC/FQDN в pydantic; 409 на дубли и пересечения.
  • Запись в audit_log — в сервисном слое в одной транзакции с изменением.

Структура репозитория

app/ main.py config.py db.py security.py
     models/ schemas/ services/ api/v1/
alembic/ (миграция 0001 — вся схема + seed: admin, типы устройств)
web/     index.html, app.js, api.js, styles.css  (IBM Plex, токены цвета из макетов)
tests/   (минимум)
docs/changes/001-ipam-backend/ PLAN.md, SUMMARY.md
docker-compose.yml  Dockerfile  .env.example  requirements.txt  README.md  venv/ (в .gitignore)

UI (web/)

Экраны 1:1 с макетами: логин, Обзор, Префиксы (вкладки VRF, фильтры, «Управление VRF»), Адреса подсети, Организации, Операторы, Устройства («Управление типами»), модальные формы. Только fetch к /api/v1, JWT в sessionStorage; 401 → экран логина. Пункт «Журнал» — заглушка со ссылкой на /audit (по вопросу №1 из макета).

Порядок работ (по артефактам из CLAUDE.md)

  1. Создать docs/changes/001-ipam-backend/PLAN.md (этот план) — до кода.
  2. Каркас: docker-compose (postgres:16 + app), Dockerfile, config, venv, Alembic.
  3. Модели + миграция 0001 + seed.
  4. Auth (login/JWT/роли; viewer — только чтение).
  5. Справочники: организации, VRF, операторы, типы, устройства.
  6. Префиксы и адреса: вложенность, использование, next-free, проверка «адрес ∈ префикс», пересечения в VRF.
  7. Обзор + audit.
  8. UI SPA.
  9. Тесты, обновить README.md, написать SUMMARY.md.

Тесты (минимум, pytest + реальный Postgres из compose)

  1. Логин → защищённый эндпоинт (401 без токена, 200 с токеном).
  2. Префикс: дубль в VRF → 409; адрес вне префикса → 422.
  3. Использование префикса и next-free считаются верно.
  4. Удаление VRF/типа «в использовании» → 409.

Проверка end-to-end

docker compose up -d --build → alembic upgrade head отрабатывает автоматически → pytest зелёный → открыть http://localhost:8000/ (UI), войти admin, пройти сценарий: организация → VRF → префикс → назначить адрес → увидеть его в Обзоре и в audit. http://localhost:8000/docs — Swagger.

Допущения (скажите, если не так)

  • VRF принадлежит организации (в макете «общий список для организации»).
  • Свободные адреса вычисляются, а не хранятся.
  • Экран «Журнал» с ротацией/очисткой (страница ROS Manager) в этот этап не входит — только запись и чтение audit.
  • Начальный пароль admin задаётся через .env, не хардкодится.

Уточнения по итогам утверждения

  • План утверждён пользователем; сохранён в этом файле до начала кода.
  • Тесты выполняются против приложения, поднятого в контейнерах (docker compose). Учётные данные для тестов генерируются автоматически (случайные пароль admin и секрет JWT в .env, файл в .gitignore). Контейнеры локальные, без внешнего доступа.
  • Сборка и запуск вспомогательных инструментов (pytest, линтеры, alembic) — из venv/ в корне проекта.
  • Обязательная сверка UI собранного приложения с макетами (все экраны и диалоги страницы «IPAM Manager»); расхождения устраняются до завершения работы, результат сверки фиксируется в SUMMARY.md.