Files
dc-observatio/docs/аудит-проекта-2026-06-06.md
T
Дмитрий Соловьев 345529cde0 chore: сохранение текущих изменений (deploy local-bundle/local-jar, request-service, slots UI markedObjectIds)
Безопасный коммит незакоммиченной работы перед реализацией бронирования слотов.
Вне коммита оставлены: package-lock.json (пустой, мусор), requests.json (scratch-данные).
2026-06-11 14:00:12 +03:00

14 KiB
Raw Blame History

Аудит проекта observatio-terrae

Дата: 2026-06-06. Автор: Claude (Opus 4.8). Охват: фронтенд pcp-tgu-ops-ui + бэкенд-сервисы. Сервис tle-monitoring-service по указанию исключён из анализа.

Метод: статический разбор кода, прогон сборки/тестов фронта, выборочное чтение бэкенд-сервисов (акцент на недавно дорабатываемых: tgu, mission-planing, complex-mission, request), проверка конфигов, CORS, обработки ошибок и гигиены репозитория.

Сводка по состоянию

Базовое здоровье — хорошее. Фронтенд проходит строгую типизацию (tsc -b, exit 0) и все тесты (53 теста в 12 файлах, зелёные); в исходниках нет console.*, any, @ts-ignore. Бэкенд использует общий GlobalExceptionHandler из pcp-types-lib, нет printStackTrace, нет @Disabled/@Ignore тестов. Найденные проблемы — это в основном технический долг, копипаст-артефакты и один реальный риск надёжности в Camunda-воркерах.

Приоритеты: B1 (надёжность), R1/C1 (гигиена/конфиги), затем рефакторинг-долг.


Бэкенд

B1 (высокий). Camunda job-воркеры молча проглатывают исключения

Файл: FlowService.kt

Все воркеры объявлены с autoComplete = false и обёрнуты в:

catch (ex : Exception) { logger.warn(ex.message) }

Если исключение возникает до client.newCompleteCommand(...).send(), задача не завершается и не падает: воркер «съел» ошибку. Camunda не получает ни complete, ни fail/incident — BPMN-процесс зависает молча до таймаута активации, без видимого инцидента и без явной диагностики. Плюс logger.warn(ex.message) теряет stack trace, а ex.message может быть null.

Рекомендация: в catch завершать задачу через client.newFailCommand(job.key) (с retries) либо бросать исключение наверх, чтобы Camunda создала incident; логировать как logger.error(msg, ex) со стек-трейсом. Это касается surveyPlan, surveyDrop, sendPlan, confirmPlan и прочих воркеров файла.

B2 (средний). Симуляционная заглушка Thread.sleep(5000) в проде-пути

Файл: FlowService.kt:97

В sendPlan стоит Thread.sleep(5000) с комментарием «Иммитация сообщения о получении подтверждения» — синхронно блокирует поток job-воркера на 5 с и эмулирует приём подтверждения плана. Для MVP-демо допустимо (см. практику осознанных заглушек), но это нужно снять при интеграции с реальной шиной подтверждений; пока имитация маскирует отсутствие реального канала и держит поток пула воркеров.

B3 (средний). Несогласованные пакеты — копипаст-артефакты

Базовые пакеты ряда сервисов не соответствуют их имени (видимо, форки шаблона):

Сервис Пакет Проблема
pcp-ballistics-service space.nstart.pcp.pcp_request_service пакет от request-сервиса
pcp-complex-mission-service space.nstart.pcp.pcp_satellites_service чужое имя
pcp-ui-service space.nstart.pcp.slots_service совпадает со slots-service
slots-service space.nstart.pcp.slots_service тот же пакет, что у ui-service
pcp-tgu-service space.nstart.pcp_tgu_service пропущен сегмент .pcp.
pcp-request-service org.nstart.dep265.requestservice другой корень (org вместо space)

Последствия: grep/навигация по пакету выводит на «не тот» сервис, IDE-импорты обманчивы,

ui-service и slots-service неотличимы по пакету. Переименование пакетов затрагивает много файлов — делать осознанно, отдельной задачей; новые сервисы заводить уже с корректным пакетом.

B4 (низкий). Опечатка «srpring» растиражирована

pcp-srpring-boot-admin-server — опечатка в имени каталога и пакета, продублированная в settings.gradle.kts, build.gradle.kts, .gitlab-ci.yml, deploy/local-bundle/docker-compose.yml, config-repo/application-docker-local.yaml. Косметика, но фиксируется во всей инфраструктуре, потому исправлять дорого — оставить как известный долг или чинить вместе с B3.

B5 (низкий). Потеря stack trace при логировании

~9 мест вида logger.warn(ex.message) / logger.error(ex.message) логируют только текст без исключения. Для диагностики предпочтительно logger.error("...", ex).

B6 (инфо). Опечатки в лог-сообщениях

Напр. «Утверждение поана» (план), «Иммитация» (имитация) в FlowService.


Фронтенд (pcp-tgu-ops-ui)

F1 (средний). Дублирование HTTP-/error-обвязки в API-клиентах

extractErrorText скопирован в 5 файлах: tguApi.ts, ballisticsApi.ts, missionPlanningApi.ts, complexPlanApi.ts, tguPlanApi.ts. Шаблон try { fetch } catch { TguApiError("network") } + разбор !response.ok повторяется ~22 раза (7 в missionPlanningApi, 5 в tguPlanApi и т.д.). В tguApi.ts уже есть аккуратный fetchJson<T>() — остальные клиенты переписывают то же руками.

Рекомендация: вынести единый src/api/http.ts (обёртка fetchJson + extractErrorText + маппинг ошибок) и переиспользовать. Сократит ~150 строк и устранит расхождения (см. F5).

F2 (низкий). Островок нетипизированного JS во вкладке «Группировка»

features/constellation/* — это .jsx/.js (ConstellationDashboard.jsx, sim.js, data.js, MapView.jsx, Panels.jsx, Timeline.jsx, util.js), включён через allowJs. Остальное приложение — строгий TS. Прототипный код подключён в прод через ConstellationTab.tsx (обёртка с as ComponentType). Типы в нём фактически any — провал строгой типизации в этой ветке UI. Долг: постепенно перевести на .tsx или хотя бы добавить декларации типов на границе.

F3 (низкий). Мёртвый barrel constellation/index.js

features/constellation/index.js (реэкспорт SIM, SATELLITES, STATIONS, ...) нигде не импортируется — можно удалить.

F4 (низкий). God-компонент TguEditorTab.tsx (1727 строк)

Самый крупный файл фронта; держит десятки useState/useRef, режимы правой панели, построение маршрутов, валидацию, undo/redo. Хорошо закомментирован, но монолитен. Кандидат на декомпозицию (вынос хуков useDraftHistory, useRouteBuilder, разнесение панелей) для снижения связности.

F5 (инфо). Расхождение приоритета полей ошибки

В tguApi.extractErrorText порядок полей reason, message, error, detail, а в missionPlanningApi.extractErrorTextmessage, error, reason, detail. При едином ответе бэка пользователь увидит разный текст из разных клиентов. Устранится при выносе общей обвязки (F1).


Гигиена репозитория

R1 (средний). Крупные дампы данных в корне репозитория (в git)

Отслеживаются git и лежат в корне:

  • pcp_requests_converted_create_requests.json (~228 КБ)
  • response_заданияКубернетс.json (~157 КБ)
  • response_заданияЕмельянов.json (~66 КБ)

Это тестовые выгрузки, засоряющие корень и историю. Перенести в docs//*/src/test/resources или убрать из git (оставив в .gitignore).

R2 (низкий). Посторонние артефакты в корне (не в git)

  • node_modules/ в корне + пустой package-lock.json ("packages": {}, 0 зависимостей) — корневого Node-проекта нет, фронт живёт в services/pcp-tgu-ops-ui. Мусор от случайного npm install в корне; удалить, при желании добавить /package-lock.json в .gitignore.
  • obj_terra.zip (~1.5 МБ) в корне — не в git, но захламляет дерево.

R3 (низкий). 26 устаревших каталогов bin/ на диске

Скомпилированные bin/main/... (gitignored) задваивают исходники: любой grep по services выдаёт каждый файл дважды (src + bin) — шум при навигации. Прогнать ./gradlew clean / удалить bin/ каталоги.


Конфигурация и безопасность

C1 (средний). Несогласованное задание паролей БД в config-repo

В большинстве сервисов пароль зашит как password: password, и только pcp-tgu-service.yaml использует переопределяемый паттерн password: ${DB_PASSWORD:password}. Для локалки риск низкий, но шаблон важен: привести все сервисы к ${DB_PASSWORD:...} (и прочие креды — к env-переменным), чтобы прод/стенды переопределялись без правки config-repo.

C2 (низкий). CORS: широкий в ui-service, отсутствует в остальных

WebConfig.kt задаёт allowedOriginPatterns("*") + allowCredentials=true — широко; для прода имеет смысл сузить origin до конкретных хостов. Остальные сервисы, которые фронт зовёт напрямую (tgu, mission, request, ballistics, complex, stations), CORS-конфига не имеют — сейчас работает только потому, что обращение идёт через Vite-прокси/nginx (same-origin). Прямые кросс-доменные вызовы к ним из браузера упадут — это ограничение стоит держать в курсе при изменении схемы доступа.


Что в порядке (намеренно не правим)

  • Заглушки/тест-контроллеры/пустой контракт валидации миссии — осознанные MVP-срезы, не дефекты.
  • Прямые вызовы микросервисов из фронта через прокси (без BFF) — принятое решение этапа.
  • Naive LocalDateTime как локальное настенное время — намеренная договорённость проекта.

Рекомендованный порядок работ

  1. B1 — починить обработку ошибок в Camunda-воркерах (надёжность процессов).
  2. R1, C1 — убрать дампы из корня; унифицировать env-пароли.
  3. F1 — общий http.ts, заодно закрыть F5.
  4. B2 — снять Thread.sleep-имитацию при появлении реального канала подтверждений.
  5. Фоном: R2/R3 (чистка), F2/F4 (типизация constellation, декомпозиция редактора), B3/B4 (пакеты/опечатки) — отдельными задачами из-за широкого охвата.