Files
ripe-cidr-collector/docs/analysis-2026-09-21.md
T
ayurishchevandClaude Sonnet 5 8a549a1452 Update the project analysis after observability
Risks 1-3 closed, observations 2 and 5 closed, new observations on module
growth, stale knowledge graph and Docker image clutter; next step is the
run on real data.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 11:12:36 +03:00

17 KiB

Анализ проекта: сделано и осталось (2026-09-21, актуализация после наблюдаемости)

Состояние после 17 доработок (план и итоги каждой лежат в docs/): надёжность и безопасность, тесты в контейнере, форматы вывода, разделение процессов, управление ASN/FQDN через API, контейнер приложения, SQLite, POST /collect, GET /addresses/diff, репозиторий git, закрепление версий, резервные копии и автовосстановление, защита ввода и данных, защита от пустой выдачи, исправления ревью 5-10, защита от пустых копий, наблюдаемость. Предыдущая версия этого файла описывала состояние после восьми доработок. Отчёт ревью: review-2026-09-21.md (находки 1-11 закрыты).

Проект: 7 модулей Python, 1719 строк (db.py 544, cidr_collector.py 386, api_server.py 381, collector_daemon.py 191, formatters.py 115, storage.py 70, healthcheck.py 32), 30 тестов (27 функций, 5 файлов и conftest.py), 37 документов в docs/ (17 планов, 17 итогов, 2 анализа, ревью), 9 коммитов, ветка main синхронизирована с origin (artstore.rxmsk.ru).

Что изменилось с предыдущей версии этого файла

  • Закрыты риски: 1 (нет git), 2 (версии не закреплены), 3 (пустой список после порчи базы).
  • Закрыты наблюдения: 2 (/health не видел сбоев источников) и 5 (сообщение «data saved» без изменений); наблюдения 10 и 11 (структура модулей) переосмыслены, наблюдение 3 ухудшилось, добавлено наблюдение 13.
  • Из «Не сделано» выполнено: автоматическая резервная копия, diff, повторные запросы к RIPE; /metrics исключён из плана решением пользователя.
  • Новое: восстановление из копии, состояние источников (/sources), фильтрация DNS-адресов, защита от пустой выдачи и пустых копий, схема базы версии 3, ревью по графу знаний (11 находок).
  • Метрики: строк кода 1719 (было 1235), тестов 30 (было 18), документов 37 (было 20).

Сделано

Направление Результат
Токен на изменяющие запросы X-API-Key на POST/DELETE, без токена запись отключена (503); сравнение по байтам, любой неверный ключ - 401. Чтение открыто намеренно.
TTL, атомарная запись, защита от порчи TTL (ttl_days), атомарная запись JSON и транзакции SQLite, битые файлы уходят в *.corrupt-*.
Форматы вывода, агрегация CIDR, ip_version nftables, mikrotik, bird, frr.
Разделение сборщика и API Отдельный демон, singleton, heartbeat, /health по status.json.
Управление ASN и FQDN через API Добавление, удаление, purge, старение данных удалённых источников.
Контейнер приложения Dockerfile (все модули корня, проверка импорта при сборке) и docker-compose.yml: два сервиса, том, non-root, read-only, healthcheck.
SQLite Таблица addresses, WAL, автоматическая миграция из JSON, транзакции; схема версии 3 (журнал изменений, состояние источников).
POST /collect Токен, ответ 202, запрос демону файлом (опрос каждые 5 с), объединение запросов, 503 без живого демона.
GET /addresses/diff?since= Журнал изменений на триггерах, курсор или время, 410 за горизонтом, X-Changes-Cursor в /addresses; строгий разбор since.
Репозиторий и версии git, origin; requirements с точными версиями и constraints.txt (полный pip freeze).
Резервные копии и восстановление Задание backup (онлайн-копия, quick_check, ротация backup_keep); при порче базы восстановление из последней исправной копии; last_restore в /health.
Защита от пустой выдачи Потеря базы без копий или восстановление из пустой копии при настроенных источниках: метка db_recreated.json, 503 на /addresses и /addresses/diff до нового сбора; пустая база не копируется.
Данные DNS и внешний источник Фильтр глобальных адресов (allow_non_global_ips), повторы запросов к RIPEstat с sourceapp и потолком Retry-After.
Наблюдаемость Состояние каждого источника (таблица source_status), блок sources и degraded в /health, GET /sources, итоговая строка запуска в логе.
Ревью и граф знаний Отчёт ревью (11 находок, все закрыты), граф graphify-out/ (вне git и образа).
Тесты 30 проверок, запуск в контейнере, изоляция файлов состояния (conftest.py).

Не сделано

Направление Статус
Запуск на реальных данных Не начато (см. наблюдение 1); следующий шаг
Уведомления (webhook, Telegram) Не начато; основа (журнал, /health, /sources) есть
Метрики Prometheus (/metrics) Исключены из плана решением пользователя; при необходимости - отдельная доработка
Ограничение частоты POST /collect Не начато
Архитектурный рефакторинг Не начато: вынос путей в settings.py, разделение api_server.py, cidr_collector.py и db.py
Копии вне сервера Не начато: копии лежат на том же томе, что и база (вынос описан в README)
TLS перед API Не начато (решение пользователя: порт наружу без TLS)

Остаточные риски

# Риск Статус
1 Нет репозитория git. Закрыт
2 Версии в requirements.txt не закреплены. Базовый образ python:3.11-slim не закреплён по дайджесту (осознанно). Закрыт
3 Пустой список после порчи базы. Остаются не покрытые случаи: ручное удаление файла базы (порчи нет, пустая база создаётся без метки) и порча внутри файла (503 при чтении, восстановление вручную). Закрыт, остаток описан
4 MikroTik и FRR не проверены на реальном ПО. Не закрыт
5 Токен идёт по HTTP открытым текстом. Осознанный выбор
6 Один общий токен, без ротации и аудита. Не закрыт
7 Тестов минимум, что соответствует правилам проекта. Осознанно
8 POST /collect без ограничения частоты: повторные запросы во время сбора пропускаются, но защиты от нагрузки на RIPE нет (при этом запросы к RIPEstat теперь идут с повторами). Не закрыт
9 Журнал diff и состояние источников проверены только на копиях и тестах: размер и нагрузка на реальных данных неизвестны. Не закрыт
10 Копии базы лежат на том же томе, что и база: защита от порчи файла, но не от потери тома. Не закрыт (описан в README)
11 Нет активных оповещений: о сбое источников можно узнать только опросом /health или из лога. Не закрыт

Наблюдения

# Наблюдение Состояние
1 Изменения не применены к реальным данным. В каталоге проекта нет ripe.db; data.json (6 ASN) и fqdn_data.json (4 имени) остались в старом формате; всё проверено только на копиях. Первый запуск на боевых данных выполнит миграцию сразу до схемы версии 3: last_seen старых записей станет равным времени миграции, журнал diff и состояние источников начнутся пустыми (клиентам стартовать с X-Changes-Cursor), первые запуски сбора создадут состояние источников. Без изменений
2 /health не видит сбоев источников. Сбои учитываются по каждому источнику, порог source_failure_threshold (по умолчанию 3): при суточном расписании FQDN это три дня до degraded. Закрыто
3 Безымянные образы Docker: 21 на хосте. Часть - от пересборок тестового образа ripe-tests при разработке, на хосте есть и чужие (docker image prune затронет все). Ухудшилось (было 3)
4 Повреждённый config.json переименовывается при чтении; первый успешный POST /asns после этого создаст файл без остальных источников, расписания и ttl_days. Без изменений
5 Сообщение «data saved» после каждой транзакции. Вместо него итоговая строка запуска. Закрыто
6 Структура README: разделы 8 (Docker) и 9 (SQLite) в конце, разделы 1-4 описывают ручную установку; за время доработок README вырос до 540 строк. Стоит перестроить: Docker и быстрый старт в начало, ручная установка ниже. Без изменений
7 google.com есть в fqdn_data.json, но не входит в конфигурацию: его адрес после миграции истечёт через 90 дней. Без изменений
8 Ручной сбор стартует не мгновенно, а в пределах 5 секунд (интервал опроса демона). Без изменений
9 Логи APScheduler о плановых запусках скрыты (чтобы опрос запросов каждые 5 с не засорял лог); остаются сообщения приложения. Без изменений
10 Общая точка отказа хранилища (по графу): главные узлы session() (22 связи), get_addresses() (15), load_full_config() (14), _recover() (14). Развязка через один тип StorageError сохраняется, но db.py (544 строки) стал самым крупным модулем и совмещает схему, восстановление, копии, журнал и состояние источников. Переосмыслено
11 Рост модулей и цикл зависимостей: db.py берёт пути и настройки из cidr_collector.py отложенным импортом внутри функций; api_server.py (381 строка) и cidr_collector.py (386) совмещают по несколько ролей. Пока работает, но следующий эндпоинт или задание усугубит. Ухудшилось
12 Граф знаний устарел и не заменяет проверку. Последнее построение (527 узлов, 1029 связей) было до доработки «наблюдаемость» (код db.py, cidr_collector.py, api_server.py, тесты и документы не отражены); хук обновления после коммита не установлен. Изолированных узлов 36 (описания без связи с кодом), расход токенов на построение не учтён (нули). Требует обновления
13 Порог degraded для FQDN: имя, разрешившееся только в неглобальные адреса (без allow_non_global_ips), через три запуска даёт degraded (no_global_addresses); источник, вернувший 0 адресов корректным ответом, degraded не вызывает, виден только в /sources. Новое

Рекомендуемый порядок

  1. Запуск на реальных данных (главный шаг). Перед запуском: копия config.json, data.json, fqdn_data.json вне каталога проекта и вне тома (миграция переименует оригиналы в *.migrated-*, но копия на случай ошибки обязательна). Затем docker compose up -d с переносом файлов в том (порядок в README), проверка /health, /sources, /addresses и /addresses/diff, первый ручной сбор через POST /collect, оценка размера базы и журнала, выбор порога source_failure_threshold. Нужен отдельный план с откатом.
  2. Обновить граф (/graphify . --update, документы выгружать целиком) и при желании поставить хук после коммита.
  3. Уведомления (webhook, Telegram) на основе журнала и состояния источников: закрывает риск 11.
  4. Архитектурный рефакторинг: settings.py (пути и умолчания), разделение db.py и api_server.py; снимает наблюдения 10-11.
  5. По мере необходимости: ограничение частоты POST /collect и ротация токена (риски 6, 8), проверка MikroTik и FRR на реальном ПО (риск 4), вынос копий за пределы тома (риск 10), TLS-прокси при внешнем доступе (риск 5), перестройка README (наблюдение 6), docker image prune (наблюдение 3).

Связанные документы

  • plan-*.md / summary-*.md (по 17): reliability-security, tests-in-container, output-formats, process-split, asn-fqdn-api, app-container, sqlite-storage, collect-endpoint, diff-endpoint, git-init, pin-dependencies, db-backup, input-hardening, loss-guard, review-fixes-5-10, empty-backup-guard, observability.
  • Ревью: review-2026-09-21.md; предыдущий анализ: analysis-2026-09-20.md.
  • Граф: graphify-out/GRAPH_REPORT.md, graphify-out/graph.html (локально, вне git).