New page /analytics/compare and API GET /admin/analytics/compare (+ /lists/{group}):
the administrator picks an old (A) and a new (B) run; the report shows the new
addresses (only in B), the ones that left (only in A) and the common ones whose
membership in the seven indicators (pass, partial, fail, egress https any/all,
ingress ssh any/all) differs, with a "what changed" summary per address; the
dynamics of each indicator (delta = new - left + entered - exited) and a verdict
transition matrix. Every number opens a list with CSV. Cancelled addresses are not
part of a run. The list dialog moved to a shared analytics-dialog.js and template;
/analytics got a "compare with another run" button.
Docs, plan and summary in docs/changes/.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
38 KiB
Cloud IP Validator
Система проверки освобождённых публичных IPv4-адресов перед их повторной выдачей. Каждый адрес временно привязывается как Floating IP
к ВМ-валидатору в облаке (OpenStack) и проверяется в двух направлениях одновременно: исходящий трафик валидатора (egress: HTTPS/ICMP/опционально SSH
до внешних целей) и входящая доступность самого адреса с нескольких независимых внешних площадок (inbound: TCP 22/80/443/8080 + ICMP).
Итог по каждому адресу — pass/partial/fail; полная история проверок сохраняется в реестре даже после удаления адреса из очереди.
Быстрый старт
go build ./... && go test ./... # сборка и юнит-тесты
scripts/run-local-e2e.sh # офлайн-прогон всей системы: mock OpenStack, без облака и интернета
cd deploy/docker
cp .env.example .env
cp control-api/control-api.docker.example.yaml control-api/control-api.docker.yaml
docker compose up -d --build # весь стенд на одной машине в mock-режиме (профили control-plane, dashboard, prober, validator)
- UI:
http://<хост>:8090/, API:http://<хост>:8080/api/v1, проверка живости:GET /healthz. - Docker-стенд работает с
openstack.mode: mockи тестовыми адресами203.0.113.10–12; реальный OpenStack и учётные данные не нужны. - Реальный стенд (systemd или Docker на нескольких хостах) — по шагам в docs/SETUP.md.
Конфигурация
Каждый компонент читает свой YAML (примеры — configs/*.example.yaml). Учётные данные OpenStack в YAML не хранятся — только имена переменных окружения.
control-api (control-api.yaml)
| Ключ | Назначение |
|---|---|
server.listen_addr |
Адрес API (:8080) |
database.path |
Файл SQLite (/var/lib/cloud-ip-validator/control-api.db) |
openstack.mode |
real или mock (встроенная заглушка OpenStack для разработки и тестов) |
openstack.auth_method |
token (готовый токен проекта из OS_TOKEN, сам не обновляется) или password (логин/пароль Keystone, токен перевыпускается автоматически) |
openstack.*_env |
Имена переменных окружения: OS_AUTH_URL, OS_PROJECT_ID, OS_REGION_NAME, OS_INTERFACE, OS_TOKEN либо OS_USERNAME/OS_USER_DOMAIN_NAME/OS_PASSWORD |
orchestrator.poll_interval_seconds |
Период такта оркестратора (5) |
orchestrator.self_check_timeout_seconds, max_self_check_retries |
Ожидание self-check валидатора (60). max_self_check_retries устарело и не используется: потолок провалов self-check задаётся настройкой self_check_max_attempts (по умолчанию 5, /settings) |
orchestrator.checking_window_seconds |
Сколько ждать результаты проверок, прежде чем подвести итог; отсчёт от начала проверки (120) |
orchestrator.lease_ttl_seconds, max_retries |
Лизинг адреса за валидатором (180) и число возвратов в очередь при его истечении (3) |
orchestrator.heartbeat_timeout_seconds |
После скольких секунд тишины валидатор или площадка считаются потерянными (30) |
orchestrator.fip_settle_seconds |
Только начальное значение: пауза между привязкой FIP и self-check; далее управляется на лету. Должно выполняться fip_settle_seconds + self_check_timeout_seconds < lease_ttl_seconds |
orchestrator.fip_scan_interval_seconds |
Периодический скан Floating IP (0 — выключен). Не выполняется, пока включён автоматический цикл |
orchestrator.fip_scan_timeout_seconds |
Предел всего сканирования Floating IP (1800) |
openstack.list_page_size, list_page_retries, request_timeout_seconds |
Скан читает Floating IP страницами (200), повторяя страницу при обрыве/5xx/429 (5 раз); таймаут одного запроса к OpenStack (60 с) |
auth.admin_token_env, auth.agent_token_env |
Имена переменных окружения с токеном администратора (CONTROL_API_ADMIN_TOKEN) и токеном агентов (CONTROL_API_AGENT_TOKEN). Значения в YAML не хранятся; пустой токен — соответствующий уровень API открыт (с предупреждением в логе) |
aggregation.missing_counts_as_fail |
Отсутствие ответа источника засчитывается как провал (true) |
validators, sites, check_types, targets, inbound_checks |
Начальная загрузка пустой БД: валидаторы (validator_id + os_port_id), внешние площадки, типы и цели egress-проверок, порты inbound-проверок. Дальше источник истины — БД, правки через API/UI |
ip_addresses |
Адреса, которые доливаются в очередь при каждом старте (только новые) |
Остальные компоненты
| Компонент | Ключи |
|---|---|
validator-agent |
validator_id, control_api_url, control_api_token_env (CONTROL_API_AGENT_TOKEN), poll_interval_seconds, self_check.* (таймаут, methods — ip_echo/control_api, ip_echo_urls), checks.* (таймауты HTTPS/ICMP, число ICMP-пакетов, ssh.*) |
prober |
site_id, control_api_url, control_api_token_env (CONTROL_API_AGENT_TOKEN), poll_interval_seconds, checks.* (таймауты TCP/ICMP, число ICMP-пакетов) |
admin-dashboard |
server.listen_addr (:8090), control_api.base_url, control_api.timeout_seconds, control_api.token_env (ADMIN_DASHBOARD_CONTROL_API_TOKEN), auth.username_env / password_env / session_secret_env (ADMIN_DASHBOARD_USERNAME / _PASSWORD / _SESSION_SECRET), auth.session_ttl_minutes (480), overview.last_completed_count (20), overview.poll_interval_seconds (5) |
Секреты (токены, пароль дашборда, ключ сессии) задаются только переменными окружения; генерация — openssl rand -hex 32. Подробности и порядок включения — docs/SETUP.md.
Настройки, меняющиеся на лету (пауза перед self-check, глубина истории, типы inbound-проверок, автоматический цикл, валидаторы, площадки, цели), хранятся в БД и правятся через API или страницу /settings.
Архитектура
| Слой | Технологии |
|---|---|
| Backend | Go 1.26, net/http (маршруты Go 1.22), SQLite (чистый Go-драйвер modernc.org/sqlite, WAL, одно соединение), встроенные миграции 0001–0008 |
| Облако | Интерфейс FloatingIPClient: реальный клиент OpenStack Neutron и MockClient |
| UI | Серверный рендеринг (Go-шаблоны) + htmx и Alpine.js, шрифты и скрипты лежат в репозитории, внешних зависимостей нет |
| Сборка | Статические бинарники (CGO_ENABLED=0) в bin/, Docker-образы, systemd-юниты |
| Компонент | Роль | Состояние | Где работает |
|---|---|---|---|
control-api |
Ведёт очередь адресов и реестр их истории, назначает валидаторов, агрегирует результаты. Единственная точка, с которой общаются все остальные компоненты | Хранит (SQLite) | Одна управляющая машина |
validator-agent |
Привязывает к себе выданный Floating IP и прогоняет egress-проверки до внешних целей | Без состояния | Каждая ВМ-валидатор в облаке |
prober |
Проверяет входящую доступность адреса снаружи (TCP/ICMP) — с независимой от облака сети | Без состояния | Каждая внешняя тестовая площадка |
admin-dashboard |
Браузерная админ-панель — то же, что API control-api, но графически. Опционален |
Без состояния | Любая машина с доступом к control-api |
Все четыре общаются только через HTTP API control-api. Pull-модель: validator-agent и prober сами опрашивают control-api, он к ним не обращается.
Схемы control/data plane — docs/DIAGRAMS.md.
cmd/ control-api validator-agent prober admin-dashboard
internal/ config db orchestrator httpapi openstack dashboard agentcore probercore checkrunner apiclient
db/migrations/ схема SQLite (0001–0008)
configs/ примеры конфигураций компонентов
deploy/ docker/ (compose, Dockerfile, RUN.txt) systemd/ (юниты)
rxprod-compose/ compose реального стенда (control-api на :8081, дашборд на :8091)
scripts/ run-local-e2e.sh httpstub/ (заглушки целей для e2e)
bin/ готовые бинарники linux/amd64 и SHA256SUMS
docs/ документация и планы доработок
Модель данных и правила
ip_queue (текущая очередь) · ip_registry (все адреса, когда-либо бывшие в очереди) · checks (результаты по циклам) · events (журнал) · validators · sites · target_groups · check_types · settings · inbound_checks_settings · auto_cycle.
Очередь и состояния
- Путь адреса:
queued→assigning_fip→awaiting_self_check→checking→aggregating→doneилиfailed. Все переходы, кроме команд оператора, выполняет оркестратор сам по таймеру. - Терминальные состояния:
done,failed,occupied.occupied— Floating IP к моменту привязки уже занят чужим портом: цикл проверки не стартует,overall_resultпуст, это неfail. - Оператор может отменить проверку (
failed+cancelled), перепроверить завершённый адрес (возврат вqueued) или удалить адрес из очереди. - Адреса обрабатываются в порядке
sequence; каждый свободный валидатор получает следующийqueued-адрес под лизинг. Истёкший лизинг возвращает адрес в очередь, послеmax_retries— вfailed.
Итоговый результат
pass— прошли все проверки: исходящие и все настроенные площадки по всем портам и ICMP.partial— часть прошла, часть нет.fail— не прошла ни одна проверка или адрес не дошёл до проверок (self-check не подтвердился).cancelled— остановлено оператором.- Итог подводится, когда отчитались валидатор и все настроенные площадки либо истекло
checking_window_seconds(отсчёт от начала проверки). Молчание источника — провал (aggregation.missing_counts_as_fail). - Проверки фиксируются в момент вердикта: результат после него не сохраняется (событие
result_dropped), каждая площадка зондирует адрес один раз за попытку. Вердикт всегда совпадает с сохранёнными проверками. - Площадки опциональны: с пустым списком
sitesитог строится только по egress-проверкам.
Запуски и аналитика
- Запуск — одна партия проверок: открывается, когда адрес попадает в пустую или обработанную очередь, принимает всё, что добавлено или перепроверено, пока открыт, и завершается, когда у всех его адресов есть итог. Перепроверка после завершения открывает новый запуск; результаты запусков не пересекаются.
- Страница «Аналитика» показывает один завершённый запуск по фактическим проверкам: показатели, причины
partial, подсети (список — в настройках), цели и типы проверок, площадки, классы ошибок, валидаторы; списки адресов выгружаются в CSV.
Реестр
- Запись реестра создаётся при первой постановке адреса и не удаляется: она переживает удаление из очереди и повторное добавление.
- История проверок хранится по циклам;
history_retention_cyclesограничивает глубину (0 — без ограничения), сама запись реестра остаётся.
Автоматический цикл (опционально, по умолчанию выключен)
- Один цикл: очистить очередь → просканировать Floating IP (фаза
scanning, фоновое задание) → дождаться, пока все адреса станут терминальными → паузаinterval_seconds→ заново. Пауза считается от завершения цикла. Сканирование не блокирует оркестратор; чужое идущее сканирование цикл дожидается, а не присоединяется к нему. interval_seconds— по умолчанию 3600, минимум 60;max_run_seconds— максимальное ожидание проверок (0 — без лимита), по истечении исходtimeout.- Исходы цикла:
completed,no_free_ips,timeout,error,stopped. Опустевшая очередь посреди цикла считается завершением. - Состояние хранится в БД и переживает перезапуск; выключение не прерывает идущие проверки. Подробности — docs/USAGE.md.
Удаление и сканирование
- Удаление (точечное, списком, «очистить всё») убирает строку очереди, но не историю в реестре.
- Скан Floating IP ставит в очередь только свободные адреса (не привязанные ни к одному порту); уже идущие проверки не трогаются. Он идёт в фоне и читает облако страницами: подходит и для тысяч адресов (на стенде 6441 Floating IP читаются ≈ 1,5–2 мин). Адреса ставятся в очередь только после полного обнаружения (кусками по 500, по возрастанию IP); при сбое чтения очередь не меняется.
dry_run=true/ «Пробное сканирование» считает адреса, не меняя очередь. - Пропускная способность: ≈ 50 с на адрес на валидатор — очередь из 6440 адресов это ≈ 18 ч на 5 валидаторах, ≈ 9 ч на 10 (рычаги: число валидаторов и
fip_settle_seconds).
API (/api/v1)
| Область | Эндпоинты |
|---|---|
| Валидатор | POST /agents/register, POST /agents/{id}/heartbeat, GET /agents/{id}/assignment, GET /agents/{id}/observed-ip, POST /agents/{id}/self-check|events|results|complete |
| Пробер | POST /probers/register, POST /probers/{site_id}/heartbeat, GET /probers/{site_id}/assignments, POST /probers/{site_id}/results |
| Очередь | GET /admin/status, GET|POST /admin/ips (limit/offset/state/q/result/order — постранично), GET /admin/ips/{ip}, POST /admin/ips/{ip}/cancel, DELETE /admin/ips/{ip}, POST /admin/ips/delete|clear, POST|GET /admin/ips/scan (фоновый скан: 202, dry_run, wait; статус и прогресс) |
| Реестр | GET /admin/registry (limit/offset/q/last_result/run/subnet — постранично; в строке — уровни egress/ingress с разбивкой по типам), GET /admin/registry/{ip} |
| Аналитика | GET /admin/analytics/runs, GET /admin/analytics/runs/{id}, GET /admin/analytics/runs/{id}/lists/{kind} (JSON или ?format=csv), GET/PUT /admin/config/subnets |
| Автоцикл | GET|PUT /admin/auto-cycle, POST /admin/auto-cycle/start|stop |
| Конфигурация | /admin/config/validators, /sites, /targets, /check-types, GET|PUT /admin/config/orchestrator, GET|PUT /admin/config/inbound-checks |
| Служебное | GET /admin/validators, GET /healthz |
Соглашения
- Тело запросов и ответов — JSON. Успех —
200,204— когда данных нет (например, у валидатора нет назначения). - Ошибки —
4xx/5xxс телом{"error": "..."}; нет или неверен токен —401(сWWW-Authenticate: Bearer), неизвестная сущность —404, конфликт состояния —409, неверные данные —400, ошибка OpenStack при скане —502. - Токен передаётся заголовком
Authorization: Bearer <токен>(docs/API.md). - Времена — RFC 3339. Полная спецификация и примеры
curl— docs/API.md.
Безопасность
- Доступ к API — два статических Bearer-токена (без срока жизни, из переменных окружения, сравнение в константное время):
Уровень Токен Методы admin CONTROL_API_ADMIN_TOKENвсе /api/v1/admin/*agent CONTROL_API_AGENT_TOKENзапись результатов валидатора и пробера: self-check,events,results,completeоткрыто — GET /healthz,register,heartbeat, получение задания (GET assignment/assignments) иGET /agents/{id}/observed-ipТокены разные: административный не открывает методы агентов, и наоборот. Валидатор и пробер получают настройку и задание без токена, но не могут отправить результат без токена агентов. - Пустой токен — уровень открыт (обратная совместимость):
control-apiстартует с предупреждением в логе. На реальном стенде задайте оба токена и ограничьте доступ на уровне сети (docs/SETUP.md); токены идут открытым текстом без TLS — публикуйте через reverse-proxy с TLS. Включать токен агентов нужно после его раздачи валидаторам и проберам (порядок). - Дашборд закрыт логином и паролем (один администратор; пароль и ключ сессии — из env). Сессия — подписанная cookie (
HttpOnly,SameSite=Strict, без состояния на сервере), CSRF-защита поOrigin, 5 неудачных входов за 10 минут с одного IP →429. Без заданных логина/пароля дашборд открыт (с предупреждением в логе). Дашборд ходит в API с токеном администратора. Подробности — docs/DASHBOARD.md. - Учётные данные OpenStack передаются только через переменные окружения процесса (
EnvironmentFile=в systemd,OS_*в Docker) и не попадают в YAML; режимpasswordперевыпускает токен сам, режимtoken— нет. - Компоненты работают по pull-модели: на валидаторах и площадках не нужно открывать входящие порты для
control-api. - Бинарники статические, без
cgo; целостность проверяетсяsha256sum -c bin/SHA256SUMS.
Публикация и эксплуатация
- Бинарники. Готовые linux/amd64 лежат в
bin/и не обновляются автоматически: после правок кода пересоберите их и обновитеSHA256SUMS(команды — docs/SETUP.md); Dockerfile копируют именноbin/*. - systemd. Юниты в
deploy/systemd/; уcontrol-api—EnvironmentFileс учётными данными OpenStack. - Docker.
deploy/docker/docker-compose.yml+docker-compose.override.yml(dev, mock) илиdocker-compose.prod.yml(без публикации портов,restart: unless-stopped). Какие сервисы поднимаются на хосте, задаётCOMPOSE_PROFILES:control-plane,dashboard,prober,validator. БД — volumecloud-ip-validator-db. Массовая доставкаvalidator-agentна валидаторы (сборка образа на каждом хосте, замена контейнера) — Ansible-сценарийdeploy/ansible/. - Реальный стенд.
rxprod-compose/— compose с готовыми образами, собственнымcontrol-api.yamlи каталогом БДcapi-db/;.envс учётными данными в репозиторий не входит. - Миграции применяются при старте
control-api; версия схемы —PRAGMA user_version. Начальная загрузка (validators,sites,targets,check_types,inbound_checks) выполняется только в пустые таблицы. - Остановка (
SIGTERM) корректно завершает HTTP-сервер и фоновые циклы. Состояние автоцикла и очереди сохраняется в БД.
Интерфейс
Страницы admin-dashboard (подробно — docs/DASHBOARD.md):
| Страница | Назначение |
|---|---|
/overview |
Счётчики и прогресс («Готово D из T», оценка времени), «в работе», «в очереди: Q», «последние завершённые», поиск по IP и фильтр по статусу, индикатор скана и автоцикла; работает на счётчиках и ограниченных списках, поэтому быстрый и при тысячах адресов |
/ips, /ips/{ip} |
Очередь постранично с поиском и фильтром на сервере: добавление адресов, «Сканировать Floating IP» (панель прогресса) и «Пробное сканирование», перепроверка, отмена, удаление (страница или «все N по фильтру», «Очистить всё»); детали и события адреса |
/registry, /registry/{ip} |
Реестр всех адресов (постранично) и полная история проверок адреса; поиск, фильтр и страница сохраняются в адресной строке. Последний результат разделён на уровни Egress и Ingress: «успешно из всего» по каждому и по типам проверок (icmp, ssh, tcp, https…) |
/analytics |
Аналитика одного завершённого запуска: показатели, причины partial, подсети, провалы по целям и типам проверок, ingress по площадкам, классы ошибок, валидаторы; выбор запуска; списки адресов с выгрузкой в CSV |
/validators, /sites, /targets, /check-types |
Управление валидаторами, внешними площадками, группами целей и типами проверок |
/settings |
Панель «Автоматический цикл», пауза перед self-check, потолок провалов self-check на адрес, глубина истории, TCP-порты и ICMP для inbound-проверок |
- Порядок блоков на
/overviewфиксирован: статистика → фильтр → таблицы; поллится только блок таблиц, поэтому набранный в фильтре текст не сбрасывается. - Ошибки control-api показываются баннером; при недоступном API страница остаётся рабочей.
- Тёмная и светлая темы, переключатель в шапке.
Тесты
go build ./... && go vet ./... && go test ./... # юнит-тесты: db, orchestrator, httpapi, dashboard, agentcore, probercore, checkrunner, openstack
go test -race ./internal/orchestrator ./internal/httpapi ./internal/dashboard ./internal/db
scripts/run-local-e2e.sh # сквозной прогон: lease-reclaim, перепроверка, автоматический цикл
Юнит-тесты используют временную SQLite и MockClient, внешних ресурсов не требуют. E2E поднимает все компоненты локальными процессами с включёнными токенами (проверяет 401/открытые маршруты и работу агента и пробера с токеном) и завершается ненулевым кодом при провале проверок автоцикла — docs/LOCAL_E2E.md.
Документация
| Документ | Для чего |
|---|---|
| docs/SETUP.md | Развёртывание с нуля: бинарники или сборка из исходников, конфигурация, systemd и Docker/docker-compose — пошагово |
| docs/USAGE.md | Повседневная работа: очередь, сканирование Floating IP, автоматический цикл, статус, реестр и история, разбор результатов |
| docs/API.md | Спецификация HTTP API control-api и примеры запросов (curl) |
| docs/DASHBOARD.md | Устройство admin-dashboard: страницы, поиск и фильтр, обработка ошибок |
| docs/ADMIN_CLEANUP.md | Ручная очистка БД администратором (SQL): сброс данных перед новым прогоном, журнал событий, реестр проверок, отдельные адреса, резервная копия и восстановление |
| docs/DIAGRAMS.md | Диаграммы потоков данных: control plane, egress-проверка, телеметрия |
| docs/LOCAL_E2E.md | Полностью офлайн-прогон всей системы одним скриптом |
| docs/changes/ | Планы доработок и отчёты ревью с отметкой времени в имени файла (последняя: скан при тысячах адресов) |
| docs/CONTROL_DATA_PLANE.html | Презентационные схемы control/data plane для docker-compose-деплоя — открыть в браузере |
История изменений
Дизайн крупных доработок зафиксирован в планах docs/PLAN_*.md; остальное — в истории git (git log).
| Изменение | Документ |
|---|---|
Веб-панель администратора admin-dashboard |
план · описание |
| Динамическое управление конфигурацией и очередью через API | план · API |
| Удаление адресов: точечное, массовое, «очистить всё» | план |
Пауза перед self-check после привязки Floating IP (fip_settle_seconds) |
план · USAGE |
| Механизм аутентификации OpenStack-клиента (token / password) | план |
| Дата | Веха | Документ |
|---|---|---|
| 2026-10-04 | Аналитика: сравнение двух запусков (/analytics/compare): новые, выбывшие и изменившиеся адреса, динамика по семи индикаторам, матрица переходов вердикта; API analytics/compare |
план · итог |
| 2026-10-04 | Аналитика: карточки pass, partial, fail открывают список адресов с этим вердиктом и выгрузку в CSV (lists/verdict_*) |
план · итог |
| 2026-10-04 | Повтор после сбоя self-check — на другом валидаторе: валидатор, проваливший self-check, этому адресу больше не выдаётся; потолок провалов self_check_max_attempts (по умолчанию 5, миграция 0012); поле self_check_failed_on |
план · итог |
| 2026-10-03 | Раздел «Аналитика»: запуски проверки (миграция 0011), показатели и списки адресов по запуску, подсети, CSV; сайдбар: связь с control-api и выход наверху, группы разделов; фильтры реестра по запуску и подсети |
план · итог · макет · USAGE · API |
| 2026-10-03 | Вердикт без опоздавших результатов: проверки фиксируются в момент вердикта, площадка зондирует адрес один раз за попытку, окно проверки считается от её начала, время записи по часам сервера (checks.recorded_at) |
план · итог · API · USAGE |
| 2026-10-03 | Реестр: последний результат по уровням Egress и Ingress, «успешно из всего» и разбивка по типам проверок (поля egress, ingress, last_cycle_id в GET /admin/registry) |
план · итог · USAGE · API |
| 2026-10-02 | Валидатор не получает второй адрес при потере heartbeat (иначе адреса уходили в fail без проверок); heartbeat агента в отдельном потоке; быстрая очистка очереди, не зависящая от соединения клиента |
план · анализ инцидента · USAGE |
| 2026-10-02 | Самопроверка через ручку control-api (self_check.methods, способ control_api рядом с IP-echo); отвязка Floating IP при провале self-check |
план · API |
| 2026-10-01 | Скан Floating IP при тысячах адресов: фоновый постраничный скан с прогрессом, фаза scanning в автоцикле, постраничные /ips и /registry, «Обзор» на счётчиках |
план · ревью и тесты · USAGE · API |
| 2026-10-01 | Аутентификация: токены администратора и агентов для API, логин и пароль для дашборда | план · ревью и тесты · API |
| 2026-10-01 | Автоматический цикл проверок по сценарию: очистка → скан FIP → проверка → пауза | USAGE · API |
| 2026-09-23 | Сканирование Floating IP и устойчивый реестр адресов с настраиваемой глубиной истории | USAGE |
| 2026-09-23 | Поиск по IP и фильтр по статусу на «Обзоре» и «Реестре» | DASHBOARD |
| 2026-09-23 | Пошаговое руководство по развёртыванию в Docker | SETUP |
| 2026-09-18 | Массовая перепроверка в дашборде; compose реального стенда rxprod-compose |
DASHBOARD |
| 2026-09-13 | Состояние occupied: пропуск цикла для уже занятого Floating IP; схемы control/data plane |
DIAGRAMS |
| 2026-08-26 | Управление внешними площадками и heartbeat пробера, новый UI дашборда, переключатель темы | DASHBOARD |