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>
8.7 KiB
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)
- Создать
docs/changes/001-ipam-backend/PLAN.md(этот план) — до кода. - Каркас: docker-compose (postgres:16 + app), Dockerfile, config, venv, Alembic.
- Модели + миграция 0001 + seed.
- Auth (login/JWT/роли; viewer — только чтение).
- Справочники: организации, VRF, операторы, типы, устройства.
- Префиксы и адреса: вложенность, использование, next-free, проверка «адрес ∈ префикс», пересечения в VRF.
- Обзор + audit.
- UI SPA.
- Тесты, обновить
README.md, написатьSUMMARY.md.
Тесты (минимум, pytest + реальный Postgres из compose)
- Логин → защищённый эндпоинт (401 без токена, 200 с токеном).
- Префикс: дубль в VRF → 409; адрес вне префикса → 422.
- Использование префикса и next-free считаются верно.
- Удаление 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.