# Отношения с апстримом Портал СОНИКС — out-of-tree форк [SatNOGS Network](https://satnogs.org/) от Libre Space Foundation. Апстрим не отслеживается автоматически: изменения переносятся вручную и только при необходимости. ## Что унаследовано * Доменная модель: `Station`, `Observation`, `Satellite`, `Transmitter`, `DemodData`, `Tle` и их связи. * Схема планирования наблюдений и структура заданий для клиента. * Формат REST API и большая часть имён полей. * Служебные скрипты `bin/djangoctl.sh` и `soniks.sh`. * `CONTRIBUTING.md` — руководство Libre Space Foundation, включая Developer's Certificate of Origin. * Лицензия AGPL-3.0. Следы апстрима в именах остались там, где их переименование сломало бы контракт с клиентами станций: префикс zip-архивов `satnogs-observations`. Поля `satnogs_*` станции удалены 2026-09-10 — их никто не читал; конфигурация станции теперь в `desired_config`. ## Апстрим — это два репозитория, а не один Главное, что нужно знать, прежде чем что-то сравнивать или переносить: после точки расхождения (2021) `satnogs-network` **удалил у себя** модели `Satellite`, `Transmitter`, `Tle` и `Mode`. Теперь он ходит за каталогом в SatNOGS DB по HTTP (`network/base/db_api.py`, `network/base/cache.py` у них) и денормализует нужное прямо в `Observation`. СОНИКС пошёл в обратную сторону — впитал модели satnogs-db внутрь `network.base`. Из этого следует три вещи: 1. Сравнивать нужно СОНИКС с **объединением** `satnogs-network` + `satnogs-db`. То, чего «нет» у нас относительно network, часто есть у нас из db. 2. `db_api.py` / `cache.py` переносить бессмысленно: у нас эти таблицы локальные. 3. Денормализация `Observation` у апстрима вынужденная — FK ставить не на что. У нас снимок наблюдения (`transmitter_*`, `station_*` в `Observation`) сделан сознательно, ради неизменности истории. Мотивы разные, результат нужен один и тот же. Каталог у нас ведут администраторы, а не сообщество: workflow предложений satnogs-db (`SatelliteEntry` / `TransmitterEntry` с рецензентом) и мультиветтинг наблюдений (`ArtifactVetting`, истина большинством голосов) сознательно не переносятся. ## Что добавлено в СОНИКС | Область | Отличие | |---|---| | Аналитика | Приложение `network.analytics` целиком: суточные метрики по сети и станциям, дашборд, API. См. [](../analytics.md) | | Источники TLE | Клиент Space-Track, приоритет источников с окном свежести (`network/base/tle_priority.py`), публичная выдача с отбором по возрасту. См. [](../tle.md) | | Публикация TLE | `POST /api/tles/` для внешних сервисов определения орбиты, с OIDC-аутентификацией | | Запуски | `Launch`, `SatelliteLaunch` и отдельный планировщик `launch_scheduler.py` | | Расчёт пролётов | Переход на `skyfield` и `sgp4` (поддержка Alpha-5) вместо `ephem`, общие примитивы в `skyfield_pass_utils.py` | | Авторизация | OIDC через Keycloak (`mozilla-django-oidc`) | | Оценка | Исправление завышенных оценок и команда `recalculate_observation_ratings`. См. [](../rating.md) | | Инфраструктура | Свой пайплайн GitLab CI с ssh-деплоем на стенд и прод. См. [](deploy.md) | | Локализация | Русский интерфейс наравне с английским | | Сеть | Прокси только для `db.satnogs.org` (`SATNOGS_DB_PROXY_URL`) | | Версионирование API | `/api/v2/` (`network/api/urls_v2.py`) с зафиксированным контрактом; всё новое — там, `/api/` не меняется. Внутри `/api/` новые поля выдаются по объявлению `?capabilities=` | | Загрузка артефактов | Идемпотентность по SHA-256: повтор теми же байтами — подтверждение приёма, другими — перезапись оборвавшейся загрузки | | Пакеты данных | `/api/v2/bundles/` — определения спутников для станций в закрытом контуре | | Тесты | 85+ тестов API против трёх у апстрима; jest с jsdom для фронтенда | ## Интеграция с сетью SatNOGS Форк не разрывает связь с апстримом, а потребляет его данные: * `fetch_data` (раз в час) тянет спутники и передатчики из SatNOGS DB (`DB_API_ENDPOINT`); * `parse_data_from_satnogs` (ежедневно, только в проде) забирает кадры SatNOGS Network за прошедшие сутки (`NETWORK_API_ENDPOINT`); * `https://db.satnogs.org/api/tle/?format=3le` — один из источников TLE, с наименьшим приоритетом. ## Перенос изменений из апстрима Прямого слияния веток нет. Практика такая: 1. Оценить, затрагивает ли изменение апстрима код, который в СОНИКС уже разошёлся (планирование, TLE, оценка наблюдений — разошлись сильнее всего). 2. Переносить точечным патчем, а не слиянием. 3. Прогнать тесты расчётных модулей — они и написаны как страховка от расхождений: `test_pass_predictions.py`, `test_prediction_windows.py`, `test_tle_priority.py`, `test_scheduling_migration.py`. Merge-request'ы по самому СОНИКС отправляются в GitLab-репозиторий проекта, а не в апстрим.