# Service Landscape Report

**Источник:** архив `pcp.zip`  
**Корень анализа:** `pcp/`  
**Дата анализа:** 2026-04-28  
**Метод:** статический анализ Gradle-модулей, `config-repo`, REST-контроллеров, Kafka listeners/producers, Camunda/Zeebe workers, JPA entities, Flyway migrations, сервисных классов и DTO. Сборка и запуск сервисов не выполнялись.

## 1. Executive summary

В архиве находится multi-module Kotlin/Spring Boot система PCP с набором backend-сервисов, UI/BFF, общими библиотеками DTO/баллистики, Spring Cloud Config server и Spring Boot Admin. Основной домен системы — работа с заявками на съемку/наблюдение, спутниками, орбитальными расчетами, слотами доступности, комплексным планированием, миссиями и передачей/подтверждением планов.

Ключевые бизнес-возможности:

- ведение заявок на съемку и их геометрий;
- ведение каталога спутников, групп и профилей съемки/слотов;
- загрузка и хранение TLE, расчет орбитальных производных данных;
- расчет зон видимости, flight line, RVA, MPL-кандидатов и покрытий;
- расчет и бронирование слотов;
- построение комплексного плана и снимков режимов КА;
- планирование миссий, режимов съемки/сброса и подтверждение планов;
- интеграция с Camunda/Zeebe для процессов спутникового плана;
- UI/BFF для карты, каталога, заявок, слотов, станций и complex-plan.

Главная архитектурная картина:

- `pcp-request-service` владеет заявками, сеткой Земли и route-matching состоянием.
- `pcp-satellite-catalog-service` владеет справочником спутников и профилей.
- `tle-monitoring-service` владеет исходными TLE и публикует события TLE.
- `pcp-ballistics-service` владеет производными баллистическими данными: PDCM, asc nodes, flight line, покрытиями и cell covering.
- `slots-service` владеет слотами, бронированиями и initial conditions для слотов.
- `pcp-complex-mission-service` хранит старую/основную модель комплексной миссии: satellite modes, snapshots, complex plan run.
- `pcp-dynamic-plan-service` реализует отдельный новый контур complex-plan run с собственным хранилищем артефактов.
- `pcp-mission-planing-service` владеет миссиями, планами, режимами и связью режимов со слотами.
- `pcp-tgu-service` владеет tracked-plan состоянием, статусами планов и процессом запуска `createSatelliteMission`.
- `pcp-ui-service` не владеет доменными данными, а выступает UI/BFF и синхронно вызывает backend-сервисы.

Самые важные интеграционные потоки:

1. TLE flow: `tle-monitoring-service` загружает TLE и публикует событие в `pcp.tle`; `pcp-ballistics-service` потребляет его и пересчитывает орбитальные данные.
2. Initial conditions flow: `slots-service` публикует initial conditions в тот же topic `pcp.tle`; `pcp-ballistics-service` потребляет событие другого типа и строит производные данные.
3. Route passport flow: `pcp-route-processing-service` читает `pcp.request.survey-georeference.v1`, публикует `pcp.route.in.v1` и `pcp.route.georeference.v1`; `pcp-request-service` обновляет покрытие заявок, `pcp-mission-planing-service` обновляет статус режима.
4. Mission/slot status flow: `pcp-mission-planing-service` подтверждает миссию и публикует `BookedSlotsStatusChangedEvent` в `pcp.slots.status.v1`; `slots-service` обновляет статусы booked slots.
5. Complex mission flow: `pcp-complex-mission-service` синхронно оркестрирует request/catalog/ballistics/slots/coverage и сохраняет modes/snapshots/run.
6. New complex-plan flow: `pcp-dynamic-plan-service` синхронно забирает заявки и баллистические данные, сохраняет run artifacts, intervals и MPL candidates.
7. TGU/Camunda flow: `pcp-tgu-service` строит план по окнам видимости, запускает BPMN process `createSatelliteMission`, хранит tracked plan и подтверждает его через worker `updatePlanStatus`.

Ключевые риски:

- в системе есть два похожих контура complex planning: `pcp-complex-mission-service` и `pcp-dynamic-plan-service`, у обоих есть сущности `complex_plan_run*`; без явного контракта владения это риск split-brain и дублирования логики;
- topic `pcp.tle` используется для разных типов событий: TLE update и initial conditions/RVA; это требует фильтров и повышает риск ошибочной обработки;
- явного transactional outbox/idempotency слоя почти не видно; часть Kafka consumers имеет частичные проверки дедупликации, но общий at-least-once дизайн не оформлен;
- `pcp-dynamic-plan-service` имеет Gradle-зависимость от `:services:pcp-request-service`, что создает compile-time coupling между сервисами;
- `pcp-ui-service` и orchestration-сервисы строят длинные синхронные HTTP/WebClient цепочки;
- Camunda workers в `pcp-mission-planing-service` ловят исключения и логируют их без явного `fail`/`throw` после catch; это может приводить к подвисанию job, если ошибка случилась до complete;
- именование части модулей и пакетов содержит опечатки (`srpring`, `planing`) и исторические package names, что усложняет навигацию и эксплуатацию.

## 2. Services overview table

| Service | Main responsibility | Main inputs | Main outputs | Storage | External dependencies | Notes |
|--------|---------------------|-------------|--------------|---------|------------------------|-------|
| `spring-cloud-config-server` | Централизованная выдача конфигураций | HTTP Config Server requests от клиентов | YAML config для сервисов | Git/config repo | `config-repo` Git URI | Инфраструктурный сервис |
| `pcp-srpring-boot-admin-server` | Spring Boot Admin UI/monitoring | Actuator/admin registrations | Admin UI/status | Нет доменного storage | Spring Boot Admin clients | Название модуля содержит опечатку `srpring` |
| `pcp-ui-service` | UI/BFF для карты, каталога, заявок, слотов, миссий | Browser HTTP, UI REST endpoints | HTML views, proxy calls | Нет | request, catalog, ballistics, stations, slots, mission, complex-mission, coverage-scheme | Tight BFF coupling к backend API |
| `pcp-request-service` | Заявки, сетка Земли, projection заявки на ячейки, route matching | REST `/api/v1/requests`, legacy `/api/requests`, `/api/earth-grid`; Kafka `pcp.request.in.v1`, `pcp.route.georeference.v1` | DB state, HTTP responses | PostgreSQL `pcp_requests` | Kafka, geometry libraries | Source-of-truth для заявок и Earth grid |
| `pcp-route-processing-service` | Преобразование route passport сообщений в route events | Kafka `pcp.request.survey-georeference.v1`; test REST | Kafka `pcp.route.in.v1`, `pcp.route.georeference.v1` | Нет | Kafka | Stateless routing/normalization service |
| `pcp-satellite-catalog-service` | Каталог спутников, групп и профилей | REST `/api/satellites`, `/api/satellite-groups` | DB state, HTTP responses | PostgreSQL `pcp_satellite_catalog` | Нет явных downstream API | Source-of-truth для satellite metadata |
| `pcp-stations-service` | Каталог наземных станций | REST `api/stations` | DB state, HTTP responses | PostgreSQL `pcp_stations` | Нет явных downstream API | Малый CRUD-сервис |
| `tle-monitoring-service` | Загрузка, хранение и публикация TLE | REST `v1/api/tle`, scheduled CelesTrak load | Kafka `pcp.tle` | PostgreSQL `pcp_tle` | CelesTrak, satellite catalog/complex-mission config | Source-of-truth для исходных TLE |
| `pcp-ballistics-service` | Баллистические расчеты и хранение производных орбитальных данных | REST `/api/satellites`, `/api/tle`, `/api/rva`, `/api/obj-view`; Kafka `pcp.tle` | DB state, HTTP responses | PostgreSQL `pcp_ballistics` | Kafka, ballistics-lib | Source-of-truth для derived ballistics artifacts |
| `slots-service` | Слоты, покрытия, бронирования, initial conditions | REST `/api/slots`, `/api/slots/booking`, `/api/satellite`, `/api/satellite-ic`; Kafka `pcp.slots.status.v1` | DB state, Kafka `pcp.tle` | PostgreSQL `pcp_slots` | request-service, satellite-catalog, Kafka | Source-of-truth для slots/bookings |
| `pcp-complex-mission-service` | Оркестрация комплексной миссии и snapshots спутниковых режимов | REST `/api/com-plan`, `/api/satellites` | DB state, HTTP calls to downstream services | PostgreSQL `pcp_satellites` | request, catalog, ballistics, slots, coverage-scheme, stations | пересекается с dynamic-plan-service |
| `pcp-dynamic-plan-service` | Новый/отдельный engine complex-plan runs и persisted artifacts | REST `/api/v1/complex-plan/runs` | DB state, HTTP calls | PostgreSQL `pcp_complex_plan` | request-service, ballistics, satellite-catalog | Имеет compile-time Gradle dependency на request-service |
| `pcp-coverage-scheme-service` | Stateless расчет coverage scheme | REST `/api/coverage-schemes/calculate` | HTTP response | Нет | ballistics, complex-mission/satellite data | Алгоритмический stateless сервис |
| `pcp-mission-planing-service` | Миссии, планы, режимы съемки/сброса, подтверждение миссий | REST `/api/missions`; Kafka `pcp.route.in.v1`; Camunda jobs | DB state, Kafka `pcp.slots.status.v1`, Camunda complete/message | PostgreSQL `pcp_missions` | complex-mission, ballistics, stations, Kafka, Camunda | Название содержит `planing`; worker behavior требует внимания |
| `pcp-tgu-service` | ТГУ-планы, external points, tracked plans, запуск Camunda process | REST `/api/plans`, `/api/satellite-missions`, `/api/plan-confirmations`, `/api/platforms`; Kafka `pcp.tgu.kpp-update.v1`; scheduled jobs; Camunda job | DB state, Camunda process instance/complete | PostgreSQL `pcp_tgu` | classifier API, ballistics/external API, Kafka, Camunda | Связан с процессом `createSatelliteMission` |
| `pcp-complex-mission-flow` | Прототип/экспериментальный flow controller | REST FlowController | HTTP calls | Нет явного DB | complex-mission, earth-grid | Модуль закомментирован в `settings.gradle.kts`; вероятно не активен |

## 3. Service-by-service analysis

### 3.1 `spring-cloud-config-server`

#### Purpose

Инфраструктурный Config Server, отдающий конфигурации из `config-repo` остальным сервисам.

#### Responsibilities

- поднимать Spring Cloud Config Server;
- выдавать YAML-конфигурации по имени приложения/profile;
- централизовать адреса сервисов, порты, PostgreSQL, Kafka, Camunda, topic names и feature settings.

#### What this service does not own

- Не владеет доменными данными.
- Не выполняет бизнес-логику PCP.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| HTTP | Spring Cloud Config endpoints | Config client request | `SpringCloudConfigServerApplication` | Отдать конфигурацию сервиса |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| HTTP response | Service clients | YAML/properties | Spring Cloud Config | Runtime configuration |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `config-repo/*.yaml` | Конфигурации сервисов | `server.port`, datasource, Kafka, services URLs | Developers/ops | Config Server, services | Git/config storage, не доменная БД |

#### Main business flows

Не участвует в бизнес-флоу, только в bootstrap/config flow.

#### Error handling and reliability

Spring Cloud Config стандартно зависит от доступности `config-repo`/Git URI. Доменной retry/idempotency логики нет.

#### Configuration

- `config-repo/spring-cloud-config-server.yaml`.
- Local port в общем `application-local.yaml`: `38888`.
- Default server port в сервисной конфигурации: `${SERVER_PORT:8888}`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `services/spring-cloud-config-server/...Application.kt` | Boot application / Config Server |
| `config-repo/*.yaml` | Централизованные настройки всех сервисов |

#### Open questions / unclear parts

- Unknown: фактическая prod Git URI/credentials не анализировались за пределами config files.

---

### 3.2 `pcp-srpring-boot-admin-server`

#### Purpose

Spring Boot Admin сервер для наблюдения за приложениями через actuator/admin client.

#### Responsibilities

- принимать регистрации admin clients;
- показывать статус приложений и actuator metadata.

#### What this service does not own

- Не владеет доменной моделью PCP.
- Не является API gateway.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| HTTP | Spring Boot Admin UI/API | Admin registration/status | `PcpSrpringBootAdminServerApplication` | Monitoring UI |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| HTTP | Browser/admin clients | Admin UI/status | Spring Boot Admin | Observability |

#### Data ownership and storage

Не обнаружено доменной БД.

#### Configuration

- `config-repo/pcp-srpring-boot-admin-server.yaml`.
- Local/default admin port в общем config: `7000` / `${pcp.ports.admin:38889}`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `services/pcp-srpring-boot-admin-server/...Application.kt` | Boot Admin application |

#### Open questions / unclear parts

- В названии модуля есть опечатка `srpring`; в Helm директории используется `pcp-spring-boot-admin-server`. Это может быть эксплуатационной неоднозначностью.

---

### 3.3 `pcp-ui-service`

#### Purpose

UI/BFF сервис для пользовательского интерфейса PCP. Он отдает HTML views и предоставляет proxy/API endpoints к backend-сервисам.

#### Responsibilities

- страницы карты, каталога, RVA, complex-plan и станций;
- проксирование/агрегация данных заявок, сетки, слотов, спутников, станций, миссий и coverage scheme;
- фасад для frontend-операций без собственного доменного хранения.

#### What this service does not own

- Не владеет заявками, слотами, спутниками, станциями, миссиями или баллистическими данными.
- Не должен содержать source-of-truth бизнес-правила; его роль — UI/BFF.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| HTTP page | `/map`, `/groups`, `/satellites`, `/rva`, `/com-plan` | Browser request | UI controllers | Отдать UI pages |
| HTTP API/proxy | `/api/catalog/**` | catalog DTOs | catalog controllers/adapters | CRUD/просмотр каталога через UI |
| HTTP API/proxy | `/api/stations` | station DTOs | station controllers/adapters | Работа со станциями |
| HTTP API/proxy | `/api/requests/**`, `/requests/**` | request/grid DTOs | request/map controllers | Работа с заявками и визуализацией |
| HTTP API/proxy | `/api/slots/**`, `/api/satellite/**`, `/api/satellite-ic/**` | slot/satellite IC DTOs | slot/map controllers | Работа со слотами и IC |
| HTTP API/proxy | `/api/com-plan/**` | complex plan request/response | complex plan controllers | Запуск/просмотр complex mission plan |
| HTTP API/proxy | coverage-scheme endpoints | coverage DTOs | coverage adapter | Расчет покрытия для UI |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| HTTP/WebClient | `pcp-request-service` | request/grid DTOs | `EarthService`, request adapters | Заявки, сетка, request visualization |
| HTTP/WebClient | `pcp-satellite-catalog-service` | satellite/group/profile DTOs | `SatelliteCatalogService` | Каталог спутников |
| HTTP/WebClient | `pcp-ballistics-service` | orbit/flight-line/asc-node/RVA DTOs | `BallisticsService` | Баллистические данные для UI |
| HTTP/WebClient | `pcp-stations-service` | station DTOs | `StationService` | Станции |
| HTTP/WebClient | `slots-service` | slots/bookings/IC DTOs | `SlotService` | Слоты и бронирования |
| HTTP/WebClient | `pcp-mission-planing-service` | mission/mode DTOs | `MissionService` | Режимы и миссии |
| HTTP/WebClient | `pcp-complex-mission-service` | complex plan DTOs | `ComplexMissionService` | Complex mission views/actions |
| HTTP/WebClient | `pcp-coverage-scheme-service` | coverage scheme DTOs | `CoverageSchemeService` | Расчет покрытия |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| Нет доменных таблиц | UI/BFF stateless | — | — | — | Storage не обнаружен |

#### Main business flows

- UI action → BFF controller → WebClient call к backend сервису → response в UI.
- Complex-plan UI → `pcp-complex-mission-service`/`pcp-dynamic-plan-service` depending on endpoint usage.
- Map/request UI → `pcp-request-service`, `slots-service`, `pcp-ballistics-service`.

#### Error handling and reliability

- Основной механизм — синхронные HTTP/WebClient вызовы.
- Unknown: единая политика timeout/retry/fallback по всем BFF adapters не прослежена как отдельный инфраструктурный слой.

#### Configuration

- `config-repo/pcp-ui-service.yaml`.
- Local port: `7008`.
- Downstream URLs: request/earth-grid, complex-mission, satellite-catalog, ballistics, stations, slots, mission, coverage-scheme.

#### Important classes

| Class/File | Role |
|-----------|------|
| `services/pcp-ui-service/.../controller/*Controller.kt` | UI pages and proxy endpoints |
| `services/pcp-ui-service/.../service/*Service.kt` | WebClient adapters к backend services |
| `config-repo/pcp-ui-service.yaml` | URLs downstream-сервисов |

#### Open questions / unclear parts

- Unknown: является ли UI единственным внешним API для пользователей или есть прямые клиенты backend-сервисов.
- Risk: BFF напрямую знает много backend endpoints; изменения контрактов backend ломают UI без промежуточного API boundary.

---

### 3.4 `pcp-request-service`

#### Purpose

Source-of-truth сервис для заявок на съемку/наблюдение, их геометрий, projection на Earth grid и обработки route matching.

#### Responsibilities

- CRUD заявок через новый `/api/v1/requests` и legacy `/api/requests` API;
- хранение исходной и остаточной геометрии заявки;
- хранение статуса заявки и процента покрытия;
- хранение Earth grid и связей заявка ↔ ячейка;
- прием заявок из Kafka `pcp.request.in.v1`;
- прием route georeference events из Kafka `pcp.route.georeference.v1`;
- расчет пересечения маршрута с заявками и обновление покрытия/остаточной геометрии;
- cleanup старых/закрытых заявок по расписанию.

#### What this service does not own

- Не владеет спутниками и их профилями — это `pcp-satellite-catalog-service`.
- Не владеет слотами и бронированиями — это `slots-service`.
- Не владеет баллистическими расчетами — это `pcp-ballistics-service`.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `/api/v1/requests` `POST/GET` | `RequestDto` / filters | `RequestController` | Новый API заявок |
| REST legacy | `/api/requests/**` | legacy request DTOs/params | `LegacyRequestsCompatController` | Совместимость со старым UI/API |
| REST | `/api/earth-grid/**` | grid filters | `EarthGridCompatController` | Работа с Earth grid и cells |
| REST test/import | `/api/v1/test/requests/import` | import payload | `TestRequestImportController` | Тестовый/import entry point |
| Kafka consumer | `pcp.request.in.v1` | `RequestDto` | `RequestKafkaListener.consumeRequest` | Создать/обновить заявку из message broker |
| Kafka consumer | `pcp.route.georeference.v1` | `KafkaMessage<RoutePassportDto>` | `RequestKafkaListener.consumeRoute` | Обновить покрытие заявок по маршруту |
| Scheduler | cleanup cron `0 0 3 * * *` | none | `RequestCleanupScheduler` / `RequestCleanupService` | Очистка/закрытие устаревших данных |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_requests.requests` | `RequestEntity` | `RequestService` | Хранение заявки |
| DB write | `pcp_requests.request_cells` | request-cell projection | `RequestGridProjectionService` | Индексация заявки по сетке |
| DB write | `pcp_requests.request_route_matches` | route match | `RouteMatchingService` | Дедупликация/история покрытия маршрутом |
| HTTP response | UI/clients/other services | request/grid DTOs | controllers | Выдача заявок, геометрий, сетки |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `requests` | Source-of-truth заявки | `id`, `name`, `selection_start/stop`, `max_roll_angle`, `required_coverage_percent`, `importance`, `app_type`, `resolution`, `original_geometry`, `remaining_geometry`, `status`, `source`, `match_count`, `last_matched_at`, `completed_at`, `version` | REST/Kafka request flow, route matching | UI, slots, complex-plan, complex-mission | Главная доменная таблица сервиса |
| `request_cells` | Projection заявки на Earth grid cells | `request_id`, `cell_id`, coverage fields | `RequestGridProjectionService` | Earth grid/read APIs, downstream flows | Projection/read model, не самостоятельный source-of-truth |
| `earth_cells` | Earth grid cells | cell number/geometry/importance | Grid init/import | request/slots/complex-mission | Source-of-truth grid внутри request-service |
| `earth_grid_settings` | Настройки сетки | grid params | service/config/init | service | Техническая настройка grid |
| `request_route_matches` | История покрытия заявки маршрутом | `request_id`, `route_id`, unique `(request_id, route_id)` | `RouteMatchingService` | service | Используется для дедупликации route processing |

#### Main business flows

1. Создание заявки через REST/Kafka.
2. Валидация DTO и геометрии.
3. Сохранение `requests`.
4. Перестройка projection в `request_cells`.
5. При получении маршрута: проверка `route_id`, геометрическое пересечение с заявками, обновление `remaining_geometry`, `match_count`, `status`, `last_matched_at/completed_at`.
6. Выдача данных UI, slots, complex-plan и complex-mission.

#### Error handling and reliability

- Для route matching есть явный DB-level uniqueness `(request_id, route_id)` и проверка повторной обработки.
- Kafka listeners валидируют payload и могут выбрасывать исключения при неверном сообщении.
- Transaction boundaries видны на сервисном уровне, но полного outbox/event sourcing слоя не обнаружено.
- DLQ/retention/retry policy в коде явно не описаны.

#### Configuration

- `config-repo/pcp-request-service.yaml`.
- DB: `pcp_requests`.
- Kafka group: `pcp-request-service`.
- Topics: `pcp.request.in.v1`, `pcp.route.georeference.v1`.
- Local port: `7005`; dev обычно `8080` через service deployment.

#### Important classes

| Class/File | Role |
|-----------|------|
| `RequestController.kt` | Новый REST API заявок |
| `LegacyRequestsCompatController.kt` | Legacy API compatibility |
| `EarthGridCompatController.kt` | Earth grid API |
| `RequestKafkaListener.kt` | Kafka входы request/route |
| `RequestService.kt` | CRUD и доменная логика заявок |
| `RequestGridProjectionService.kt` | Projection заявки на grid cells |
| `RouteMatchingService.kt` | Обработка маршрута и покрытие заявок |
| `RequestCleanupService.kt` | Scheduled cleanup |
| `src/main/resources/db/migration/*` | Схема `requests`, `earth_cells`, `request_cells`, `request_route_matches` |

#### Open questions / unclear parts

- Unknown: какой внешний producer отвечает за `pcp.request.in.v1`.
- Unknown: политика Kafka retry/DLQ задается инфраструктурно или отсутствует.

---

### 3.5 `pcp-route-processing-service`

#### Purpose

Stateless сервис нормализации route passport сообщений: читает входной Kafka topic, парсит JSON и публикует два производных события для request-service и mission-planning.

#### Responsibilities

- потреблять `pcp.request.survey-georeference.v1`;
- парсить route passport JSON в `RoutePassportDto`;
- публиковать normalized route event в `pcp.route.in.v1`;
- публиковать georeference route event в `pcp.route.georeference.v1`;
- сохранять trace/correlation metadata в wrapper/header, если оно есть во входном сообщении.

#### What this service does not own

- Не хранит заявки, маршруты или статусы режимов.
- Не решает, какие заявки покрыты маршрутом; это делает `pcp-request-service`.
- Не решает бизнес-статус режима; это делает `pcp-mission-planing-service`.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| Kafka consumer | `pcp.request.survey-georeference.v1` | raw JSON / parsed route passport | `RoutePassportMessageListener` | Принять route passport |
| REST test | `/api/route-processing/test`, `/api/route-processing/test/send-passport-message` | test request | test controller | Локальная/ручная проверка |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| Kafka producer | `pcp.route.in.v1` | `KafkaMessage<RoutePassportDto>`, type `ModeStatusChangedEvent` | `RoutePassportKafkaPublisherService` | Событие для mission planning |
| Kafka producer | `pcp.route.georeference.v1` | `KafkaMessage<RoutePassportDto>`, type `RouteGeoRefEvent` | `RoutePassportKafkaPublisherService` | Событие для request route matching |

#### Data ownership and storage

Нет доменных таблиц; сервис stateless.

#### Main business flows

1. Получить сообщение из `pcp.request.survey-georeference.v1`.
2. Распарсить route passport.
3. Завернуть в общий `KafkaMessage`.
4. Положить type header/event type.
5. Отправить в два downstream topics.

#### Error handling and reliability

- Ошибки парсинга приводят к exception в consumer path.
- Явного DLQ/outbox/idempotency слоя не обнаружено.
- Сервис не хранит offset-level бизнес-дедупликацию.

#### Configuration

- `config-repo/pcp-route-processing-service.yaml`.
- Input topic: `pcp.request.survey-georeference.v1`.
- Output topics: `pcp.route.in.v1`, `pcp.route.georeference.v1`.
- Kafka group: `pcp-route-processing-service`.
- Local port: `7004`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `RoutePassportMessageListener.kt` | Kafka consumer |
| `RoutePassportJsonParserService.kt` | Parsing/normalization |
| `RoutePassportKafkaPublisherService.kt` | Kafka producer |
| `RoutePassportTestController.kt` | Test endpoint |

#### Open questions / unclear parts

- Unknown: внешний источник topic `pcp.request.survey-georeference.v1`.
- Risk: route event публикуется синхронно в два topic без собственного persisted outbox; при частичной ошибке возможна рассинхронизация downstream topics.

---

### 3.6 `pcp-satellite-catalog-service`

#### Purpose

Source-of-truth сервис каталога спутников, групп спутников и профилей наблюдения/слотов.

#### Responsibilities

- CRUD спутников;
- поиск спутника по NORAD;
- batch загрузка/обновление спутников;
- CRUD групп спутников;
- хранение observation profile и slot profile;
- хранение углов слота/профиля.

#### What this service does not own

- Не владеет TLE — это `tle-monitoring-service`.
- Не владеет вычисленными орбитальными данными — это `pcp-ballistics-service`.
- Не владеет слотами и бронированиями — это `slots-service`.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `/api/satellites` CRUD | satellite DTOs | `SatelliteCatalogController` | Управление спутниками |
| REST | `/api/satellites/by-norad` | NORAD id | `SatelliteCatalogController` | Поиск спутника |
| REST | `/api/satellites/{id}/observation-profile` | profile DTO | `SatelliteCatalogController` | Профиль наблюдения |
| REST | `/api/satellites/{id}/slot-profile` | slot profile DTO | `SatelliteCatalogController` | Профиль слотов |
| REST | `/api/satellites/batch` | batch DTO | `SatelliteCatalogController` | Batch operation |
| REST | `/api/satellite-groups` CRUD | group DTOs | `SatelliteGroupController` | Группы спутников |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_satellite_catalog.*` | satellite/profile/group entities | catalog services | Persist catalog state |
| HTTP response | UI, slots, complex-mission, TLE monitoring, TGU indirectly | satellite/profile/group DTOs | controllers | Выдача справочника |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `satellite` | Source-of-truth спутника | id, NORAD, name/status/platform fields | catalog API | UI, slots, complex-mission, TLE monitoring | Основная таблица каталога |
| `satellite_group` | Группы спутников | id, name | catalog API | UI/clients | Справочник групп |
| `satellite_group_satellite` | Связь group-satellite | group id, satellite id | catalog API | UI/clients | Link table |
| `satellite_observation_profile` | Профиль наблюдения | satellite id, observation params | catalog API | planning/complex flows | Domain config для расчетов |
| `satellite_slot_profile` | Профиль слотов | satellite id, slot params | catalog API | slots/complex flows | Domain config для slot calculation |
| `satellite_slot_angle` | Углы слота | profile id, angle values | catalog API | slots/complex flows | Detail table |

#### Main business flows

- UI/clients создают или редактируют спутник.
- Downstream services запрашивают каталог и профили при расчетах слотов, complex mission и TLE updates.

#### Error handling and reliability

- Стандартный CRUD/JPA flow.
- Явной messaging/idempotency логики не обнаружено.

#### Configuration

- `config-repo/pcp-satellite-catalog-service.yaml`.
- DB: `pcp_satellite_catalog`.
- Local port: `7013`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `SatelliteCatalogController.kt` | Satellite/profile REST API |
| `SatelliteGroupController.kt` | Group REST API |
| `SatelliteService.kt`, profile services | Business CRUD |
| `entity/*` | JPA mapping |
| `db/migration/*` | Schema/FK for catalog |

#### Open questions / unclear parts

- Unknown: является ли NORAD уникальным бизнес-ключом на уровне БД или только на уровне сервисной логики.

---

### 3.7 `pcp-stations-service`

#### Purpose

Source-of-truth CRUD-сервис наземных станций.

#### Responsibilities

- хранить станции;
- отдавать список/станцию по id;
- создавать/удалять станцию.

#### What this service does not own

- Не владеет баллистикой видимости станций; расчеты делаются в ballistics/coverage flows.
- Не владеет mission plans.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `api/stations` `GET/POST/DELETE` | station DTO | `StationController` | CRUD станций |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_stations.stations` | `StationEntity` | `StationService` | Persist station catalog |
| HTTP response | UI/mission/clients | station DTO | `StationController` | Выдача станций |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `stations` | Source-of-truth станции | number/name, longitude, latitude, height, elevation | station API | UI, mission/coverage flows | Малый справочник |

#### Main business flows

CRUD справочника станций.

#### Error handling and reliability

Стандартный REST/JPA flow; messaging не обнаружен.

#### Configuration

- `config-repo/pcp-stations-service.yaml`.
- DB: `pcp_stations`.
- Local port: `7009`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `StationController.kt` | REST API |
| `StationService.kt` | CRUD logic |
| `StationEntity.kt` | JPA entity |
| `db/migration/*` | Stations schema |

#### Open questions / unclear parts

- Unknown: кто является владельцем master-data станций вне PCP, если такой внешний источник есть.

---

### 3.8 `tle-monitoring-service`

#### Purpose

Сервис загрузки, хранения и публикации TLE. Он следит за TLE, подтягивает их из CelesTrak и рассылает обновления downstream-сервисам через Kafka.

#### Responsibilities

- хранить TLE records в `pcp_tle`;
- загружать TLE вручную через REST;
- периодически проверять/обновлять TLE;
- получать список спутников из catalog/complex service configuration;
- публиковать TLE update events в Kafka topic `pcp.tle`.

#### What this service does not own

- Не владеет каталогом спутников.
- Не рассчитывает орбиты/покрытия; это `pcp-ballistics-service`.
- Не владеет слотами или миссиями.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `v1/api/tle` `GET` | query/none | `TLEController` | Получить TLE |
| REST | `v1/api/tle/load-array` | TLE array DTO | `TLEController` | Ручная загрузка массива TLE |
| REST | `v1/api/tle/check-cycle` | none | `TLEController` | Ручной запуск проверки |
| REST | `v1/api/tle/from-celestrack` | NORAD/list params | `TLEController` | Загрузить из CelesTrak |
| Scheduler | fixed schedule, примерно раз в 3 часа | none | `CelesTrakService` | Периодическое обновление TLE |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| Kafka producer | `pcp.tle` | `KafkaMessage` with TLE DTO/event type | `KafkaProducer` / `CelesTrakService` | Сообщить ballistics о TLE update |
| DB write | `pcp_tle.tle` | `TLEEntity` | TLE/CelesTrak services | Сохранить TLE |
| HTTP/WebClient | satellite catalog / configured satellite service | satellite DTOs | `ComplexMissionService` naming in code | Получить список спутников для обновления TLE |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `tle` | Source-of-truth TLE records | satelliteId/NORAD, revolution, TLE lines, `time_rec` | TLE load/update flows | TLE API, Kafka publisher | Migration history содержит исправление кириллической `с` в `time_reс` → `time_rec` |

#### Main business flows

1. Получить список спутников.
2. Для каждого спутника проверить актуальность TLE.
3. Загрузить/обновить TLE из CelesTrak.
4. Сохранить TLE в DB.
5. Опубликовать событие в `pcp.tle`.
6. `pcp-ballistics-service` пересчитает производные орбитальные данные.

#### Error handling and reliability

- Scheduled load продолжает работу при ошибках отдельных операций, насколько видно по service-level try/catch/logging.
- Явного outbox для связки DB write + Kafka publish не обнаружено.
- Kafka topic shared с initial conditions событиями; корректность зависит от event type/filter downstream.

#### Configuration

- `config-repo/tle-monitoring-service.yaml`.
- DB: `pcp_tle`.
- Kafka default topic: `pcp.tle`.
- Kafka group: `pcp`.
- Service URLs: complex mission / satellite catalog settings.
- Local port: `7001`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `TLEController.kt` | REST API TLE |
| `CelesTrakService.kt` | External TLE load/update cycle |
| `KafkaProducer.kt` | Publishes TLE events |
| `TLEEntity.kt` | JPA entity |
| `db/migration/*` | TLE schema |

#### Open questions / unclear parts

- Unknown: точная политика versioning TLE events и какие event type values считаются публичным контрактом.
- Risk: DB update и Kafka publish не выглядят атомарными.

---

### 3.9 `pcp-ballistics-service`

#### Purpose

Сервис баллистических расчетов и хранения производных орбитальных данных. Он принимает TLE/initial conditions, рассчитывает орбитальные точки, asc nodes, flight lines, покрытия, cell coverage и отдает расчетные данные другим сервисам.

#### Responsibilities

- потреблять TLE update events и IC/RVA events из Kafka topic `pcp.tle`;
- рассчитывать и хранить PDCM/орбитальные точки;
- рассчитывать asc nodes, flight lines, Earth coverage, cell covering;
- предоставлять API для orbit availability, flight line, RVA, MPL point/square, exact-time position;
- очищать расчетные данные по спутнику;
- парсить TLE и рассчитывать RVA по TLE через REST.

#### What this service does not own

- Не владеет исходным TLE как master data — это `tle-monitoring-service`.
- Не владеет каталогом спутников — это `pcp-satellite-catalog-service`.
- Не владеет бронированиями/слотами — это `slots-service`.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| Kafka consumer | `pcp.tle`, event type TLE update | `TLEDTO` inside `KafkaMessage` | `SatelliteService.listener2` | Пересчитать производные данные по TLE |
| Kafka consumer | `pcp.tle`, event type IC/RVA placed | `SatelliteICDTO` | `SatelliteIcRvKafkaListener` / `SatelliteIcEventService` | Обработать initial conditions |
| REST | `/api/satellites/{norad_id}/orbit` | time interval | `SatelliteController` | Orbit points |
| REST | `/api/satellites/orbit/availability` | time/id | `SatelliteController` | Доступность орбитальных данных |
| REST | `/api/satellites/{norad_id}/asc-node` | satellite id | `SatelliteController` | Asc nodes |
| REST | `/api/satellites/{norad_id}/flight-line` | interval | `SatelliteController` | Flight line |
| REST | `/api/satellites/{norad_id}/rva` | interval | `SatelliteController` | Radio visibility area |
| REST | `/api/satellites/{satellite_id}/extract-time` | `ExactTimePositionRequestDTO` | `SatelliteController` | Position at exact time |
| REST | `/api/obj-view/mpl-square`, `/api/obj-view/mpl-point` | `ObjViewRequestDTO` | `ObjViewController` | MPL view calculations |
| REST | `/api/obj-view/cell-coverage/{number}` | cell number | `ObjViewController` | Coverage by cell |
| REST | `/api/rva` | `IcRvaRequestDTO` | `RVAController` | RVA calculation |
| REST | `/api/tle/parse`, `/api/tle/rva` | TLE DTOs | `TLEController` | TLE parse/RVA |
| REST | `/api/satellites/{satellite_id}/clear` | satellite id | `SatelliteController` | Очистка расчетных данных |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_ballistics.pdcm` | PDCM/orbit point rows | `SatelliteService` | Store orbit points |
| DB write | `asc_node`, `flight_line`, `earth_coverage`, `cell_covering` | derived ballistics artifacts | `SatelliteService` | Store derived artifacts |
| HTTP response | complex-mission, complex-plan, coverage-scheme, UI, TGU | DTOs from `pcp-types-lib` | controllers | Расчетные данные downstream-сервисам |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `pdcm` | Орбитальные точки/состояния | satelliteId, time, revolution, coordinates/velocity fields | TLE/IC processing | ballistics API, complex-plan | Derived source-of-truth внутри ballistics |
| `asc_node` | Восходящие узлы | satelliteId, time/revolution | calculation flow | clients | Derived artifact |
| `flight_line` | Линия полета | satelliteId, time/geometry | calculation flow | complex-plan, UI, coverage | Derived artifact |
| `earth_coverage` | Покрытие Земли | satelliteId, interval/geometry | calculation flow | coverage/complex flows | Derived artifact |
| `cell_covering` | Покрытие grid cell | cell number, contour geometry | calculation flow | obj-view/coverage flows | Projection/derived data |

#### Main business flows

1. TLE update:
   1. Kafka message from `pcp.tle`.
   2. Filter by TLE event type.
   3. Parse `TLEDTO`.
   4. Calculate orbital products.
   5. Persist PDCM/asc node/flight line/coverage/cell covering.
2. Initial conditions update:
   1. Kafka message from `pcp.tle` with IC event type.
   2. Parse `SatelliteICDTO`.
   3. Normalize optional coefficients.
   4. Calculate/persist derived orbit data.
3. HTTP calculation:
   1. Downstream sends satellite/time/geometry request.
   2. Service reads persisted artifacts or computes from state.
   3. Returns DTO/geometry response.

#### Error handling and reliability

- Kafka listeners use filters by event type.
- Some calculations run asynchronously/coroutine-like; exact transactional boundary between all derived tables should be reviewed for partial updates.
- No explicit outbox because this service mainly consumes and stores.
- Idempotency by satellite/time/revolution is not fully evident from report-level scan; check repository constraints before relying on it.

#### Configuration

- `config-repo/pcp-ballistics-service.yaml`.
- DB: `pcp_ballistics`.
- Kafka default topic: `pcp.tle`.
- Kafka group: `pcp-ballistics-service`.
- Calculation interval configured in config.
- Local port: `7003`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `SatelliteController.kt` | Main ballistics REST API |
| `ObjViewController.kt` | MPL/cell coverage API |
| `RVAController.kt` | RVA API |
| `TLEController.kt` | TLE parse/RVA endpoints |
| `SatelliteService.kt` | Core calculation and Kafka TLE listener |
| `SatelliteIcRvKafkaListener.kt` | IC/RVA event listener |
| `SatelliteIcEventService.kt` | IC event handling |
| `entity/*` | PDCM, asc node, flight line, coverage entities |
| `db/migration/*` | Ballistics schema |

#### Open questions / unclear parts

- Unknown: exact consistency guarantees when recalculating multiple derived tables for one satellite.
- Risk: shared topic `pcp.tle` combines multiple event families.

---

### 3.10 `slots-service`

#### Purpose

Source-of-truth сервис слотов, бронирований и satellite initial conditions. Он рассчитывает покрытия/слоты, хранит бронирования и реагирует на изменение статусов booked slots.

#### Responsibilities

- расчет слотов по полигону/заявке/интервалу;
- хранение слотов;
- бронирование и отмена слотов;
- хранение связи booked slot ↔ request;
- хранение/CRUD satellite IC;
- публикация initial conditions в Kafka topic `pcp.tle`;
- потребление событий статуса booked slots из `pcp.slots.status.v1`;
- scheduler timeout для booked slots.

#### What this service does not own

- Не владеет заявками — читает их из `pcp-request-service`.
- Не владеет каталогом спутников — читает `pcp-satellite-catalog-service`.
- Не владеет баллистическими производными данными — публикует IC, но расчеты downstream делает `pcp-ballistics-service`.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `/api/slots/test-init` | init request | `SlotController` | Инициализация/тест slot data |
| REST | `/api/slots/poly-cover`, `/api/slots/poly-cover/batch` | polygon/time/satellite data | `SlotController` | Расчет покрытия полигонов слотами |
| REST | `/api/slots/request-cover` | request id/filter | `SlotController` | Покрытие заявки |
| REST | `/api/slots/interval` | interval params | `SlotController` | Слоты за интервал |
| REST | `/api/slots/booking/**` | booking DTOs | `BookingController` | CRUD/booking/cancel booked slots |
| REST | `/api/slots/mission/**` | mission/satellite request | `MissionController` | Slot data для mission planning |
| REST | `/api/satellite/**` | satellite/IC/RVA params | `SatelliteController` | RVA/IC helper endpoints |
| REST | `/api/satellite-ic/**` | IC DTO | `SatelliteIcController` | CRUD initial conditions |
| Kafka consumer | `pcp.slots.status.v1` | `BookedSlotsStatusChangedEvent` | `BookedSlotsKafkaListener` | Обновить статусы booked slots |
| Scheduler | timeout check | none | `BookedSlotTimeoutScheduler` | Mark timed-out bookings |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `slot`, `booked_slot`, `booked_slot_request`, `satellite_ic` | slot/booking/IC entities | slot/booking/IC services | Persist slots/bookings |
| Kafka producer | `pcp.tle` | `KafkaMessage` type `ICRVPlacedEvent` | `SatelliteIcKafkaPublisher` | Передать initial conditions в ballistics |
| HTTP/WebClient | `pcp-request-service` | earth grid/request DTOs | `EarthService` | Получить заявки/cells |
| HTTP/WebClient | `pcp-satellite-catalog-service` | satellite/profile DTOs | `SatelliteCatalogClient` | Получить параметры спутника |
| HTTP response | UI, complex-mission, mission-planning | slots/booking DTOs | controllers | Выдать расчет/состояние слотов |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `slot` | Source-of-truth slot candidate/window | satellite id, interval, geometry/coverage fields | slot calculation/init | booking/mission/UI | Основная сущность слота |
| `booked_slot` | Source-of-truth бронирования слота | `slot_id`, `cycle`, status, timings | booking API, Kafka status update | mission/UI/slots | Unique `(slot_id, cycle)` |
| `booked_slot_request` | Связь booking ↔ request | `booked_slot_id`, `request_id` | booking request flow | slots/mission flows | Unique `(booked_slot_id, request_id)` |
| `satellite_ic` | Initial conditions спутника | satellite id, IC/RVA fields | IC API | publisher, UI | Данные для отправки в ballistics |

#### Main business flows

1. Slot calculation:
   1. Получить request/grid/satellite profile.
   2. Рассчитать доступные слоты/покрытие.
   3. Вернуть результат или сохранить slot state.
2. Booking:
   1. Принять booking request.
   2. Найти slot/cycle.
   3. Создать `booked_slot` и связи с request.
   4. Вернуть booking state.
3. Mission confirmation status:
   1. Получить `BookedSlotsStatusChangedEvent` из Kafka.
   2. Найти booked slots.
   3. Обновить status.
4. Initial conditions:
   1. Создать/выбрать satellite IC.
   2. Опубликовать `ICRVPlacedEvent` в `pcp.tle`.
   3. Ballistics пересчитает орбитальные производные.

#### Error handling and reliability

- Есть DB uniqueness для booked slots и booked slot requests.
- Есть timeout scheduler для зависших бронирований.
- Kafka consumer обновляет статусы, но общего DLQ/outbox слоя не обнаружено.
- REST endpoint `/api/slots/booking/process` выглядит как незавершенный/legacy path: в inventory он возвращает `Nothing`; нужно перепроверить перед использованием.

#### Configuration

- `config-repo/slots-service.yaml`.
- DB: `pcp_slots`.
- Kafka default topic: `pcp.tle`.
- Status topic: `pcp.slots.status.v1`.
- Downstream URLs: request-service/earth-grid, satellite-catalog.
- Timeout/check settings for booked slots.
- Local port: `7006`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `SlotController.kt` | Slot calculation API |
| `BookingController.kt` | Booking API |
| `MissionController.kt` | Mission-related slot API |
| `SatelliteController.kt` | IC/RVA helper API |
| `SatelliteIcController.kt` | IC CRUD API |
| `SlotService.kt` | Slot calculation/booking logic |
| `BookingService.kt` / status services | Booking lifecycle |
| `BookedSlotsKafkaListener.kt` | Status event consumer |
| `SatelliteIcKafkaPublisher.kt` | IC event producer |
| `BookedSlotTimeoutScheduler.kt` | Timeout handling |
| `db/migration/*` | Slot/booking schema |

#### Open questions / unclear parts

- Unknown: precise lifecycle enum of booked slots should be reviewed when answering status transition questions.
- Risk: IC events are published into `pcp.tle`, a topic also used for TLE updates.

---

### 3.11 `pcp-complex-mission-service`

#### Purpose

Оркестрационный и stateful сервис комплексной миссии. Он строит и хранит спутниковые режимы, snapshots и complex plan runs, вызывая request, satellite catalog, ballistics, slots и coverage-scheme сервисы.

#### Responsibilities

- запуск complex plan process через `/api/com-plan/process`;
- хранение complex plan run и run-satellite links;
- хранение satellite modes, cells, booked slots и snapshots;
- выдача режимов спутника, statistics, mission-for-paint и snapshots;
- подготовка/пересчет satellite modes;
- оркестрация расчетов через downstream services.

#### What this service does not own

- Не владеет каталогом спутников как master data.
- Не владеет заявками как master data.
- Не владеет слотами как source-of-truth booking state.
- Не владеет баллистическими вычислениями как source-of-truth.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `/api/com-plan/process` | `ComplexPlanProcessRequestDTO`, user headers | `ComplexPlanController` | Запустить complex plan run |
| REST | `/api/com-plan/runs`, `/runs/{id}`, `/runs/{id}/modes` | filters/id | `ComplexPlanController` | Читать run state |
| REST | `/api/com-plan/clear`, `DELETE /runs/{id}` | id/none | `ComplexPlanController` | Очистка run/state |
| REST | `/api/com-plan/cell-with-mars/{cell_number}` | cell number | `ComplexPlanController` | Данные ячейки с MARS/coverage context |
| REST | `/api/satellites` | filters | `SatelliteController` | Satellite modes overview |
| REST | `/api/satellites/{satellite_id}/mission*` | satellite id | `SatelliteController` | Mission/statistics/paint data |
| REST | `/api/satellites/{satellite_id}/modes` | interval, runId | `SatelliteController` | Modes by satellite/time |
| REST | snapshot endpoints | snapshot id/filters | `SatelliteController` | Snapshot read/write |
| REST | `/api/satellites/prepare` | prepare request | `SatelliteController` | Подготовка modes |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_satellites.satellite_modes*`, `complex_plan_run*` | mode/run/snapshot entities | complex mission services | Persist complex mission state |
| HTTP/WebClient | `pcp-ballistics-service` | MPL/cell/exact-time requests | `BallisticsService` | Баллистические расчеты |
| HTTP/WebClient | `pcp-request-service` | earth grid/request data | `EarthGridService` | Получить заявки/cells |
| HTTP/WebClient | `pcp-satellite-catalog-service` | satellite catalog/profile | `SatelliteCatalogClient` | Получить спутники |
| HTTP/WebClient | `slots-service` | slots/book/cancel requests | `SlotService`, `CoverageBatchClient` | Рассчитать/забронировать слоты |
| HTTP/WebClient | `pcp-coverage-scheme-service` | coverage scheme request | `CoverageSchemeCalculationClient` | Подбор coverage scheme |
| HTTP response | UI, mission planning, TLE monitoring? | modes/run DTOs | controllers | Выдача complex mission state |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `satellite_modes` | Режимы спутника | satelliteId, source, type, start/end, revolution, lat/lon, duration, contourWkt, roll, cellNum | complex mission calculation | UI, mission-planning | Stateful result of planning/calculation |
| `satellite_mode_cell` | Связь mode ↔ cell | mode id, cell id/number | calculation | UI/analytics | Projection/detail |
| `satellite_mode_booked_slot` | Связь mode ↔ booked slot | mode id, booked slot id | booking/planning flow | mission/complex | Дублирует ссылку на source-of-truth booking in slots-service |
| `satellite_mode_snapshots` | Snapshots modes | snapshot id, mode refs, metadata | snapshot flow | mission-planning | Used by mission planning `comPlanSnapshotId` |
| `complex_plan_run` | Run complex plan | id, status, requestedBy, params | `/process` flow | UI/clients | Пересекается по названию с new dynamic-plan-service |
| `complex_plan_run_satellite` | Run ↔ satellite | run id, satellite id | process flow | UI/clients | Link table |

#### Main business flows

1. Complex plan run:
   1. UI/API вызывает `/api/com-plan/process`.
   2. Сервис получает пользователя из headers.
   3. Загружает заявки/grid, спутники/profile, баллистические данные, слоты и coverage scheme.
   4. Рассчитывает modes/snapshots/run artifacts.
   5. Сохраняет state в `pcp_satellites`.
   6. Возвращает run response.
2. Satellite modes read:
   1. Клиент запрашивает modes/statistics/mission-for-paint.
   2. Сервис читает persisted modes/snapshots.
   3. Возвращает DTO для UI/mission planning.
3. Booking interaction:
   1. В ходе complex mission может вызывать slots-service для slot coverage/book/cancel.
   2. Локально сохраняет ссылки на booked slots, но source-of-truth статуса остается в `slots-service`.

#### Error handling and reliability

- Оркестрация строится на синхронных HTTP вызовах к нескольким сервисам.
- Компенсация при частично успешных calls видна не полностью; для book/cancel есть отдельные методы, но глобальная saga/transaction не оформлена как отдельный механизм.
- Нет явного outbox.

#### Configuration

- `config-repo/pcp-complex-mission-service.yaml`.
- DB: `pcp_satellites`.
- Service URLs: ballistics, request/earth-grid, complex-mission self, satellite-catalog, stations, slots, coverage-scheme.
- Local port: `7002`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `ComplexPlanController.kt` | Complex plan run REST API |
| `SatelliteController.kt` | Satellite modes/snapshots REST API |
| `ComplexPlanRunOrchestrationService.kt` | Run orchestration |
| `ComplexPlanCalculationService.kt` | Calculation core |
| `ComplexMissionService.kt` | Main service facade |
| `BallisticsService.kt`, `SlotService.kt`, `SatelliteCatalogClient.kt`, `CoverageSchemeCalculationClient.kt` | Downstream clients |
| `entity/*` | Modes/snapshots/run entities |
| `db/migration/*` | `pcp_satellites` schema |

#### Open questions / unclear parts

- Assumption: это исторически основной complex mission state сервис, а `pcp-dynamic-plan-service` — новый контур. Это следует из названий endpoints и комментариев, но явно в README не подтверждено.
- Risk: пересечение моделей `complex_plan_run` с `pcp-dynamic-plan-service`.

---

### 3.12 `pcp-dynamic-plan-service`

#### Purpose

Новый/отдельный сервис ручного запуска и хранения complex-plan run artifacts. Он строит run, сохраняет выбранные заявки, интервалы, MPL candidates и результаты.

#### Responsibilities

- принимать ручной запуск complex-plan через `/api/v1/complex-plan/runs`;
- тестовый запуск `/test-default`;
- сохранять run state;
- сохранять satellite/request snapshots для run;
- строить intervals и MPL candidates;
- выдавать run, список runs, result summary и GeoJSON intervals;
- генерировать отчет по MPL candidates для тестового запуска.

#### What this service does not own

- Не владеет исходными заявками — читает из `pcp-request-service`.
- Не владеет каталогом спутников — читает из `pcp-satellite-catalog-service`.
- Не владеет баллистическими данными — читает из `pcp-ballistics-service`.
- Не видно, что он владеет финальным booking/mission execution lifecycle.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `POST /api/v1/complex-plan/runs` | `ComplexPlanRunStartRequestDTO`, user headers | `ComplexPlanRunController.startRun` | Создать manual run |
| REST | `POST /api/v1/complex-plan/runs/test-default` | headers | `ComplexPlanRunController.startDefaultTestRun` | Тестовый default run и report |
| REST | `GET /api/v1/complex-plan/runs/{id}` | id | `ComplexPlanRunController` | Получить run |
| REST | `GET /api/v1/complex-plan/runs` | filters | `ComplexPlanRunController` | Список runs |
| REST | `GET /api/v1/complex-plan/runs/{id}/result-summary` | id | `ComplexPlanRunController` | Summary artifacts |
| REST | `GET /api/v1/complex-plan/runs/{id}/intervals/geojson` | id | `ComplexPlanIntervalGeoJsonService` | GeoJSON persisted intervals |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_complex_plan.*` | run/request/interval/MPL/result entities | `ComplexPlanCalculator`, persistence services | Persist run artifacts |
| HTTP/WebClient | `pcp-request-service` | request interval query | `HttpRequestServiceClient` | Найти заявки в интервале |
| HTTP/WebClient | `pcp-ballistics-service` | flight line/MPL data | `HttpBallisticsServiceClient` | Получить баллистические данные |
| HTTP/WebClient | `pcp-satellite-catalog-service` | satellite data | service client | Получить спутник/profile |
| HTTP response | UI/API clients | run/report DTOs | controller/query/report services | Вернуть run state |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `complex_plan_run` | Source-of-truth run в новом сервисе | run id, status, requestedBy, interval, satellite/NORAD | `ComplexPlanCalculator` | API/query services | Не тот же storage, что `pcp-complex-mission-service` |
| `complex_plan_run_satellite` | Snapshot спутника для run | run id, satellite id/NORAD/profile fields | calculator | reports/API | Run-local snapshot |
| `complex_plan_run_request` | Snapshot selected request | run id, request id, geometry/status fields | calculator | algorithms/reports | Копия данных из request-service на момент run |
| `complex_plan_interval` | Persisted planning intervals | run id, interval start/end, geometry/context | interval builder | GeoJSON/report | Derived artifact |
| `complex_plan_mpl_candidate` | MPL candidates | run id, candidate geometry/time/score fields | MPL calculation service | report/result | Derived artifact |
| `complex_plan_result` | Run result | run id, summary/status | result service | API | Итоговый artifact |
| `complex_plan_result_request` | Result ↔ request detail | result id, request id | result service | API | Detail table |

#### Main business flows

1. Manual run:
   1. Получить request payload и user headers.
   2. Создать run со статусом running/created.
   3. Найти заявки, пересекающие интервал, через request-service.
   4. Загрузить flight line/MPL данные через ballistics-service.
   5. Построить интервалы и MPL candidates алгоритмами сервиса.
   6. Сохранить artifacts.
   7. Mark completed/failed.
   8. Вернуть persisted run response.
2. Read/report:
   1. Прочитать persisted artifacts.
   2. Сформировать summary/GeoJSON/report.

#### Error handling and reliability

- Сервис явно хранит run status и mark failed/completed paths.
- Внешние HTTP-вызовы синхронные.
- Нет Kafka/outbox.
- Risk: build file зависит от `project(":services:pcp-request-service")`, что нарушает обычную независимость сервисов.

#### Configuration

- `config-repo/pcp-dynamic-plan-service.yaml`.
- DB: `pcp_complex_plan`.
- URLs: request-service, ballistics-service, satellite-catalog-service.
- Local port: `7014`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `ComplexPlanRunController.kt` | REST API run lifecycle |
| `ComplexPlanCalculator.kt` | Main orchestration/calculation |
| `HttpRequestServiceClient.kt` | Request-service client |
| `HttpBallisticsServiceClient.kt` | Ballistics client |
| `IntervalsBuilder.kt` | Interval algorithm |
| `SpaceCraftFlightLineBuilder.kt` | Flight line preparation |
| `MplCandidateCalculationService.kt` | MPL candidate algorithm |
| `ComplexPlanRunQueryService.kt` | Query run state |
| `ComplexPlanIntervalGeoJsonService.kt` | GeoJSON report |
| `ComplexPlanMplCandidateReportService.kt` | MPL candidate report |
| `db/migration/*` | `pcp_complex_plan` schema |

#### Open questions / unclear parts

- Unknown: как этот новый сервис связан с `pcp-complex-mission-service` в production flow.
- Risk: два хранилища complex-plan run state могут расходиться.

---

### 3.13 `pcp-coverage-scheme-service`

#### Purpose

Stateless алгоритмический сервис расчета coverage scheme. Он собирает данные из ballistics/complex mission и возвращает расчет, не сохраняя доменное состояние.

#### Responsibilities

- принять запрос на расчет coverage scheme;
- получить баллистические данные: MPL point/square, flight line, exact-time position;
- получить satellite/mode context из complex mission service;
- построить coverage scheme через внутренние алгоритмы;
- вернуть результат клиенту.

#### What this service does not own

- Не владеет persisted coverage state.
- Не владеет заявками, слотами, режимами или баллистическими данными.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `POST /api/coverage-schemes/calculate` | `CoverageSchemeCalculateRequestDTO` | `CoverageSchemeController` | Рассчитать coverage scheme |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| HTTP/WebClient | `pcp-ballistics-service` | ballistics requests | `BallisticsClient` | Получить расчетные данные |
| HTTP/WebClient | `pcp-complex-mission-service` | satellite data | `ComplexMissionService` client | Получить satellite context |
| HTTP response | complex-mission/UI/clients | coverage scheme DTO | `CoverageSchemeCalculationService` | Вернуть расчет |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| Нет доменных таблиц | Stateless calculation | — | — | — | Storage не обнаружен |

#### Main business flows

1. Получить coverage request.
2. Вызвать ballistics endpoints.
3. Получить satellite context.
4. Построить coverage scheme.
5. Вернуть результат без сохранения.

#### Error handling and reliability

- Синхронные HTTP calls, configured response timeout около 30s.
- Нет persistent retry/outbox, так как сервис stateless.

#### Configuration

- `config-repo/pcp-coverage-scheme-service.yaml`.
- URLs: ballistics, complex-mission, satellite-catalog.
- Response timeout and in-memory buffer settings.
- Local port: `7012`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `CoverageSchemeController.kt` | REST API |
| `CoverageSchemeCalculationService.kt` | Main calculation |
| `CoverageSchemeBuilderService.kt` | Algorithm builder |
| `BallisticsClient.kt` | Ballistics API client |
| `ComplexMissionService.kt` | Satellite context client |

#### Open questions / unclear parts

- Unknown: является ли результат coverage scheme всегда transient или где-то downstream сохраняется как part of complex mission state.

---

### 3.14 `pcp-mission-planing-service`

#### Purpose

Stateful сервис управления миссиями, планами и режимами. Он генерирует survey/drop modes, связывает их со слотами и обновляет статусы по route events и confirmation flow.

#### Responsibilities

- CRUD миссий;
- хранение plans/modes/survey modes/drop modes;
- расчет survey modes по complex mission snapshot или satellite modes;
- расчет drop modes;
- подтверждение миссии и публикация статусов booked slots;
- обновление статуса survey mode по route passport event;
- выполнение Camunda job workers для процесса satellite plan.

#### What this service does not own

- Не владеет source-of-truth слотами и booked slots; он хранит связи/снимки для миссии, но статус должен синхронизироваться со `slots-service`.
- Не владеет complex mission modes/snapshots; читает их из `pcp-complex-mission-service`.
- Не владеет баллистическими/станционными справочниками.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `/api/missions` CRUD | mission DTOs | `MissionController` | Управление миссиями |
| REST | `/api/missions/{mission_id}/modes` | mission id | `MissionController` | Режимы миссии |
| REST | `/api/missions/modes/satellite` | satellite/time | `MissionController` | Режимы по спутнику/интервалу |
| REST | `/api/missions/{mission_id}/drops/calculate` | mission id | `MissionController` | Рассчитать drop modes |
| REST | `/api/missions/{mission_id}/surveys/calculate` | mission id, `comPlanSnapshotId` | `MissionController` | Рассчитать survey modes |
| REST | `/api/missions/{mission_id}/confirm` | mission id | `MissionController` | Подтвердить миссию |
| REST | `/api/missions/survey-modes/{mode_id}/status` | status update | `MissionController` | Ручное обновление status |
| Kafka consumer | `pcp.route.in.v1` | `ModeStatusChangedEvent` / `RoutePassportDto` | `ModeStatusChangedKafkaListener` | Обновить status survey mode по route event |
| Camunda job | `calculateSatelliteSurveyMissions` | variables: `satellitePlanId`, `spacecraftId`, `planStartTime`, `planEndTime` | `FlowService.surveyPlan` | Создать mission и survey modes |
| Camunda job | `calculateSatelliteDropMissions` | `satellitePlanId` | `FlowService.surveyDrop` | Рассчитать drop missions |
| Camunda job | `sendSatellitePlan` | `satellitePlanId` | `FlowService.sendPlan` | Имитация отправки плана и publish message accepted |
| Camunda job | `updateSlotsStatus` | `satellitePlanId` | `FlowService.confirmPlan` | Confirm mission и слоты |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_missions.*` | mission/plan/mode entities | `MissionPlaningService` | Persist mission state |
| Kafka producer | `pcp.slots.status.v1` | `BookedSlotsStatusChangedEvent` | `BookedSlotsEventPublisher` | Обновить status booked slots в slots-service |
| HTTP/WebClient | `pcp-complex-mission-service` | modes/snapshots DTOs | `ComplexMissionService` | Получить satellite modes/snapshots |
| HTTP/WebClient | `pcp-ballistics-service` | ballistics DTOs | `BallisticsService` | Расчетные данные |
| HTTP/WebClient | `pcp-stations-service` | station DTOs | stations client | Данные станций |
| Camunda complete/message | Camunda broker | variables: `modes`, `slots`, message `Message_SatellitePlanAccepted` | `FlowService` | Завершение BPM jobs |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `missions` | Source-of-truth миссии | mission id, satellite id, interval, status | REST/Camunda flow | UI/TGU/process | Root entity |
| `plans` | Планы внутри миссии | plan id, mission id, stage/snapshot refs | service | service/API | `stage4SnapshotId` links to complex mission snapshot |
| `modes` | Base mode | mode id, mission/plan refs, time/type | calculation | API/process | Base table for survey/drop modes |
| `survey_modes` | Survey mode detail | mode id, satelliteModeId, status, source | survey calculation, route events | API/process | Связь с complex mission satellite mode |
| `drop_modes` | Drop mode detail | mode id, drop params | drop calculation | API/process | Drop-specific state |
| `mode_booking` | Mode ↔ booked slot | survey mode id, booked slot id | confirm/calculation | service | Ссылка на slot-service booking |
| `drop_mode_survey` | Drop ↔ survey relation | drop mode id, survey mode id | drop calculation | service | Link table |

#### Main business flows

1. Survey calculation:
   1. Создать/найти mission.
   2. Получить modes/snapshot из complex-mission.
   3. Сформировать survey modes.
   4. Сохранить modes и связи.
2. Drop calculation:
   1. Взять survey modes миссии.
   2. Рассчитать drop modes.
   3. Сохранить links.
3. Confirm mission:
   1. Найти связанные booked slots.
   2. Обновить локальное состояние миссии.
   3. Опубликовать `BookedSlotsStatusChangedEvent` в `pcp.slots.status.v1`.
   4. `slots-service` обновит source-of-truth статусы slots.
4. Route event status:
   1. Получить `pcp.route.in.v1`.
   2. Найти survey mode по route passport.
   3. Обновить status survey mode.
5. Camunda process:
   1. Worker получает job variables.
   2. Вызывает `MissionPlaningService`.
   3. Complete job с variables или publish message.

#### Error handling and reliability

- Kafka publisher sends status event; legacy HTTP status update в slots-service, по комментариям в коде, удален из main pipeline.
- Camunda workers используют `autoComplete=false`, но в `FlowService` exceptions перехватываются и логируются; после catch нет явного `fail`/`throw`. Это риск для надежности worker lifecycle.
- Явный DLQ/outbox для Kafka публикации не обнаружен.
- Transaction boundaries для сохранения mission state и Kafka publish требуют отдельной проверки перед эксплуатационными гарантиями.

#### Configuration

- `config-repo/pcp-mission-planing-service.yaml`.
- DB: `pcp_missions`.
- Kafka group: `pcp-mission-planing-service`.
- Kafka topics: `pcp.slots.status.v1`, `pcp.route.in.v1`.
- Camunda gRPC endpoint configured.
- Downstream URLs: ballistics, complex-mission, stations.
- Local port: `7010`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `MissionController.kt` | REST API missions |
| `MissionPlaningService.kt` | Core domain/application logic |
| `FlowService.kt` | Camunda workers |
| `ModeStatusChangedKafkaListener.kt` | Route event consumer |
| `BookedSlotsEventPublisher.kt` | Slot status event producer |
| `ComplexMissionService.kt`, `BallisticsService.kt` | Downstream clients |
| `entity/*` | Mission/plan/mode persistence |
| `db/migration/*` | Mission schema |

#### Open questions / unclear parts

- Unknown: complete BPMN process model was not rendered/analyzed visually; worker names and variables came from code.
- Risk: worker error handling should be fixed/verified before relying on Camunda retries.

---

### 3.15 `pcp-tgu-service`

#### Purpose

Сервис ТГУ-планирования: хранит tracked plan state, получает окна видимости/точки КА, строит ближайший план, запускает Camunda process `createSatelliteMission`, подтверждает план через worker/status API и интегрируется с внешним классификатором платформ.

#### Responsibilities

- принимать/хранить spacecraft points messages;
- периодически обновлять external points из внешнего API;
- рассчитывать ближайший plan из observation/insertion windows;
- запускать Camunda BPMN process `createSatelliteMission`;
- хранить tracked plan и process instance key;
- подтверждать plan;
- отдавать планы и external points через REST;
- проверять существование платформы через classifier API.

#### What this service does not own

- Не владеет баллистическими орбитальными расчетами; external API base URL настроен на ballistics.
- Не владеет mission planning state `pcp_missions`; он запускает BPMN-процесс, который дальше вызывает mission-planning workers.
- Не владеет каталогом спутников PCP напрямую; использует external classifier/platform API.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | `/api/external-points/{satelliteId}` | satellite id, interval | `ExternalPointsController` | Получить external points |
| REST | `/api/plans`, `/api/plans/{spacecraftId}` | filters/id | `PlanController` | Получить планы |
| REST | `/api/plan-confirmations/{planId}`, `POST /api/plan-confirmations` | plan id/request | `PlanConfirmationController` | Подтвердить plan |
| REST | `/api/platforms` | classifier filters | `PlatformController` | Прокси к classifier platforms |
| REST | `/api/satellite-missions/{noradId}` | NORAD | `SatelliteMissionController` | Запустить process создания миссии |
| Kafka consumer | `pcp.tgu.kpp-update.v1` | `SpacecraftPointsMessage` | `SpacecraftPointsKafkaConsumer` | Обновить spacecraft points |
| Scheduler | `external-update-fixed-delay-ms` | none | `ExternalPointsUpdateScheduler` | Периодически загрузить points из external API |
| Scheduler | `notification-check-fixed-delay-ms` | none | `PlanProcessScheduler` | Запустить process для планов около старта |
| Camunda job | `updatePlanStatus` | variable `satellitePlanId` | `PlanStatusWorker` | Mark tracked plan confirmed |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| DB write | `pcp_tgu.tracked_plan`, `spacecraft_planning_state` | tracked/process state | `TrackedPlanService`, `SpacecraftPlanningStateService` | Persist TGU planning state |
| HTTP/WebClient | external classifier | platform classifier request | `PlatformService` / classifier client | Проверить platform exists |
| HTTP/WebClient | external API / ballistics URL | RVA/external points request | `ExternalPointsClient` | Получить точки/окна видимости |
| Camunda create instance | Camunda broker | process `createSatelliteMission`, variables | `SatelliteMissionProcessService` | Запустить satellite mission process |
| Camunda complete | Camunda broker | complete `updatePlanStatus` | `PlanStatusWorker` | Завершить worker job |
| HTTP response | UI/clients | plan/process DTOs | controllers | Выдать статус/план |

#### Data ownership and storage

| Entity/Table/Collection | Purpose | Key fields | Written by | Read by | Notes |
|-------------------------|---------|------------|------------|---------|-------|
| `tracked_plan` | Source-of-truth tracked plan in TGU | planId, spacecraftId, start/end, processInstanceKey, status, source | scheduler/manual process start, confirmation worker | TGU APIs/schedulers | Управляет TGU lifecycle и dedup/supersede |
| `spacecraft_planning_state` | Текущее planning state по КА | spacecraftId, points/state fields | Kafka/external update flow | plan calculation | State/projection из external points |
| In-memory/domain `Plan`, `SpacecraftPoints` | Расчетные domain objects | planId, spacecraftId, windows | service layer | service layer | Не JPA source-of-truth сами по себе |

#### Main business flows

1. External points update:
   1. Scheduler или Kafka получает `SpacecraftPointsMessage`.
   2. Сохраняет planning state.
   3. Пересчитывает доступные планы.
2. Manual/auto process start:
   1. Получить NORAD/plan.
   2. Проверить платформу во внешнем classifier.
   3. Найти ближайший plan по visibility/insertion points.
   4. Зарегистрировать tracked plan.
   5. Запустить Camunda process `createSatelliteMission` с variables: `spacecraftId`, `satellitePlanId`, `planStartTime`, `planEndTime`, `kppId`.
   6. Сохранить `processInstanceKey`.
3. Confirmation:
   1. REST или Camunda worker подтверждает `planId`.
   2. `tracked_plan` получает confirmed status.

#### Error handling and reliability

- `SatelliteMissionProcessService` блокирует повторный auto-start для уже confirmed plan и при manual start supersedes previous plan.
- `PlanProcessScheduler` ловит ошибки запуска по каждому plan и логирует их.
- `PlanStatusWorker` бросает exception при отсутствии `satellitePlanId`, затем complete через `.join()`.
- Kafka/outbox для points updates не обнаружен.

#### Configuration

- `config-repo/pcp-tgu-service.yaml`.
- DB: `pcp_tgu`.
- Kafka topic: `pcp.tgu.kpp-update.v1`.
- Camunda gRPC endpoint configured.
- Classifier URL: external NSI classifier.
- External API base URL configured through ballistics service URL.
- Local port: `7011`.

#### Important classes

| Class/File | Role |
|-----------|------|
| `SatelliteMissionProcessService.kt` | Starts Camunda process `createSatelliteMission` |
| `PlanStatusWorker.kt` | Camunda worker `updatePlanStatus` |
| `PlanProcessScheduler.kt` | Auto-start process for upcoming plans |
| `ExternalPointsUpdateScheduler.kt` | Periodic external points refresh |
| `SpacecraftPointsKafkaConsumer.kt` | Kafka points consumer |
| `PlanCalculationService.kt` | Plan calculation algorithm |
| `TrackedPlanService.kt` | Tracked plan lifecycle |
| `SpacecraftPointsService.kt` | Points/state persistence and recalculation |
| `controllers/*` | REST API |
| `entity/*`, `db/migration/*` | TGU persistence |

#### Open questions / unclear parts

- Unknown: exact semantic difference between TGU plan and `pcp-mission-planing-service` mission plan must be read from BPMN/process docs.
- Assumption: TGU запускает upstream BPMN process, который затем вызывает mission-planning workers.

---

### 3.16 `pcp-complex-mission-flow`

#### Purpose

Похоже на прототип/альтернативный flow service для комплексной миссии. В `settings.gradle.kts` модуль закомментирован, поэтому он, вероятно, не входит в основную сборку.

#### Responsibilities

- FlowController для запуска flow;
- сервисы `ComplexMission`, `EarthGrid`, `Flow` для оркестрации;
- HTTP calls к complex mission / earth grid services.

#### What this service does not own

- Не владеет доменными данными.
- Не должен рассматриваться как production source-of-truth, пока не подтверждена его активность.

#### Entry points

| Type | Name / endpoint / topic / job type | Input model | Main handler/class | Purpose |
|------|------------------------------------|-------------|--------------------|---------|
| REST | Flow endpoints | flow request | `FlowController` | Запуск экспериментального flow |

#### Outputs

| Type | Target | Output model/event | Producer class | Purpose |
|------|--------|--------------------|----------------|---------|
| HTTP/WebClient | complex mission / earth grid | service DTOs | `ComplexMissionService`, `EarthGridService` | Оркестрация flow |

#### Data ownership and storage

Storage не обнаружен.

#### Main business flows

Unknown: модуль неактивен в root settings; анализировать его как production flow рискованно.

#### Error handling and reliability

Unknown.

#### Configuration

- В `config-repo/application-local.yaml` есть port `7007` для `complex-mission-flow`.
- В `settings.gradle.kts` include закомментирован.

#### Important classes

| Class/File | Role |
|-----------|------|
| `FlowController.kt` | REST entry |
| `FlowService.kt` | Flow orchestration |
| `ComplexMissionService.kt`, `EarthGridService.kt` | Downstream clients |

#### Open questions / unclear parts

- Нужно подтвердить, используется ли сервис в runtime/Helm/CI. В текущем архиве он выглядит неактивным.

## 4. Cross-service interactions

### 4.1 Interaction table

| Source service | Target service/system | Mechanism | Data sent | Purpose | Sync/Async |
|---------------|------------------------|-----------|-----------|---------|------------|
| `pcp-ui-service` | `pcp-request-service` | HTTP/WebClient | request/grid DTOs | UI operations with requests and Earth grid | Sync |
| `pcp-ui-service` | `pcp-satellite-catalog-service` | HTTP/WebClient | catalog requests | UI catalog | Sync |
| `pcp-ui-service` | `pcp-ballistics-service` | HTTP/WebClient | satellite/time/geometry requests | UI orbit/RVA/flightline | Sync |
| `pcp-ui-service` | `slots-service` | HTTP/WebClient | slot/booking/IC requests | UI slot booking and IC | Sync |
| `pcp-ui-service` | `pcp-complex-mission-service` | HTTP/WebClient | complex plan requests | UI complex plan | Sync |
| `pcp-ui-service` | `pcp-coverage-scheme-service` | HTTP/WebClient | coverage requests | UI coverage calculation | Sync |
| `pcp-ui-service` | `pcp-stations-service` | HTTP/WebClient | station requests | UI stations | Sync |
| `tle-monitoring-service` | CelesTrak | HTTP | NORAD/TLE request | Load TLE | Sync |
| `tle-monitoring-service` | `pcp-satellite-catalog-service` / configured satellite service | HTTP | satellite list request | Determine satellites for TLE update | Sync |
| `tle-monitoring-service` | `pcp-ballistics-service` | Kafka `pcp.tle` | TLE event | Trigger ballistics recalculation | Async |
| `slots-service` | `pcp-request-service` | HTTP | request/grid lookup | Slot coverage calculation | Sync |
| `slots-service` | `pcp-satellite-catalog-service` | HTTP | satellite/profile lookup | Slot calculation | Sync |
| `slots-service` | `pcp-ballistics-service` | Kafka `pcp.tle` | `ICRVPlacedEvent` / IC DTO | Trigger recalculation from IC | Async |
| `pcp-route-processing-service` | `pcp-request-service` | Kafka `pcp.route.georeference.v1` | `RoutePassportDto` | Update request coverage | Async |
| `pcp-route-processing-service` | `pcp-mission-planing-service` | Kafka `pcp.route.in.v1` | `RoutePassportDto` / mode status event | Update survey mode status | Async |
| `pcp-mission-planing-service` | `slots-service` | Kafka `pcp.slots.status.v1` | `BookedSlotsStatusChangedEvent` | Update booked slot statuses | Async |
| `pcp-mission-planing-service` | `pcp-complex-mission-service` | HTTP | mission/snapshot/mode requests | Build survey/drop modes | Sync |
| `pcp-mission-planing-service` | `pcp-ballistics-service` | HTTP | satellite/time requests | Ballistics data for planning | Sync |
| `pcp-mission-planing-service` | `pcp-stations-service` | HTTP | station lookup | Mission planning context | Sync |
| `pcp-complex-mission-service` | `pcp-request-service` | HTTP | earth grid/request lookup | Complex plan inputs | Sync |
| `pcp-complex-mission-service` | `pcp-satellite-catalog-service` | HTTP | satellite/profile lookup | Complex plan inputs | Sync |
| `pcp-complex-mission-service` | `pcp-ballistics-service` | HTTP | MPL/exact-time/cell requests | Ballistics in complex plan | Sync |
| `pcp-complex-mission-service` | `slots-service` | HTTP | slots/book/cancel requests | Slot selection/booking | Sync |
| `pcp-complex-mission-service` | `pcp-coverage-scheme-service` | HTTP | coverage request | Coverage scheme calculation | Sync |
| `pcp-dynamic-plan-service` | `pcp-request-service` | HTTP | interval request query | Select requests for run | Sync |
| `pcp-dynamic-plan-service` | `pcp-ballistics-service` | HTTP | flight line/MPL requests | Build intervals/candidates | Sync |
| `pcp-dynamic-plan-service` | `pcp-satellite-catalog-service` | HTTP | satellite lookup | Satellite context | Sync |
| `pcp-coverage-scheme-service` | `pcp-ballistics-service` | HTTP | MPL/flightline/exact-time requests | Build coverage scheme | Sync |
| `pcp-coverage-scheme-service` | `pcp-complex-mission-service` | HTTP | satellite/mode request | Satellite context | Sync |
| `pcp-tgu-service` | external classifier | HTTP | platform filter | Validate platform/NORAD | Sync |
| `pcp-tgu-service` | external API / ballistics URL | HTTP | points/RVA requests | Load external spacecraft points | Sync |
| `pcp-tgu-service` | Camunda broker | gRPC | `createSatelliteMission` variables | Start BPMN process | Sync command / async process |
| Camunda broker | `pcp-tgu-service` | gRPC job | `updatePlanStatus` | Confirm tracked plan | Async worker |
| Camunda broker | `pcp-mission-planing-service` | gRPC jobs | satellite plan variables | Calculate/confirm mission | Async worker |

### 4.2 Kafka/event map

| Topic | Producer | Consumer(s) | Event model | Partition key if visible | Purpose |
|------|----------|-------------|-------------|--------------------------|---------|
| `pcp.tle` | `tle-monitoring-service` | `pcp-ballistics-service` | TLE update event with `TLEDTO` inside `KafkaMessage` | satellite id / Unknown exact | Trigger recalculation from TLE |
| `pcp.tle` | `slots-service` | `pcp-ballistics-service` | `ICRVPlacedEvent` / `SatelliteICDTO` inside `KafkaMessage` | satellite id | Trigger recalculation from initial conditions |
| `pcp.request.in.v1` | Unknown external producer | `pcp-request-service` | `RequestDto` | Unknown | Create/update request asynchronously |
| `pcp.request.survey-georeference.v1` | Unknown external producer | `pcp-route-processing-service` | raw route passport JSON | Unknown | Ingest route passport |
| `pcp.route.in.v1` | `pcp-route-processing-service` | `pcp-mission-planing-service` | `KafkaMessage<RoutePassportDto>`, type `ModeStatusChangedEvent` | trace/route id maybe in payload | Update survey mode status |
| `pcp.route.georeference.v1` | `pcp-route-processing-service` | `pcp-request-service` | `KafkaMessage<RoutePassportDto>`, type `RouteGeoRefEvent` | route id maybe in payload | Update request coverage by route |
| `pcp.slots.status.v1` | `pcp-mission-planing-service` | `slots-service` | `BookedSlotsStatusChangedEvent` | missionId/modeId/first bookedSlotId fallback | Update booked slot statuses |
| `pcp.tgu.kpp-update.v1` | Unknown external producer | `pcp-tgu-service` | `SpacecraftPointsMessage` | spacecraft id likely | Update spacecraft points / planning state |

### 4.3 REST/gRPC dependency map

| Caller | Callee | Endpoint/method | Request | Response | Purpose |
|--------|--------|-----------------|---------|----------|---------|
| UI/BFF | request-service | `/api/v1/requests`, `/api/requests`, `/api/earth-grid` | request/grid DTOs | request/grid DTOs | UI request/grid operations |
| UI/BFF | satellite-catalog | `/api/satellites`, `/api/satellite-groups` | catalog DTOs | catalog DTOs | UI catalog |
| UI/BFF | slots | `/api/slots`, `/api/slots/booking`, `/api/satellite-ic` | slot/booking DTOs | slot/booking DTOs | UI slots |
| UI/BFF | ballistics | `/api/satellites/**`, `/api/obj-view/**`, `/api/rva` | satellite/time/geometry DTOs | orbit/RVA/coverage DTOs | UI calculations |
| UI/BFF | complex-mission | `/api/com-plan/**`, `/api/satellites/**` | complex plan params | run/mode DTOs | UI complex mission |
| complex-mission | request-service | earth grid/request APIs | interval/cell/request filters | cells/requests | Inputs to complex planning |
| complex-mission | satellite-catalog | satellite APIs | ids/batch | satellite/profile DTOs | Inputs to complex planning |
| complex-mission | ballistics | `/api/obj-view/**`, `/api/satellites/{id}/extract-time` | geometry/time | MPL/cell/position | Ballistics calculations |
| complex-mission | slots | `/api/slots/**`, `/api/slots/booking/**` | slot/booking requests | slots/bookings | Coverage and booking |
| complex-mission | coverage-scheme | `/api/coverage-schemes/calculate` | coverage request | scheme response | Build coverage scheme |
| complex-plan | request-service | request interval lookup | interval | selected requests | New complex-plan run |
| complex-plan | ballistics | flight line/MPL APIs | satellite/time/geometry | flight line/MPL data | New complex-plan run |
| coverage-scheme | ballistics | ballistics APIs | coverage calculation inputs | ballistics DTOs | Coverage scheme algorithm |
| mission-planning | complex-mission | snapshot/mode APIs | mission/snapshot ids | modes | Survey/drop modes |
| mission-planning | Camunda | job complete/publish message | variables | broker ack | BPMN task completion |
| TGU | Camunda | `newCreateInstanceCommand` for `createSatelliteMission` | process variables | process instance | Start satellite mission process |
| Camunda | TGU | job type `updatePlanStatus` | job variables | complete | Confirm tracked plan |
| Camunda | mission-planning | job types listed below | job variables | complete/message | Calculate/send/confirm satellite plan |

### 4.4 BPM/Zeebe map

| Process/Worker | Job type | Owning service | Input variables | Output variables | Error mapping |
|----------------|----------|----------------|-----------------|------------------|---------------|
| `createSatelliteMission` process start | n/a | `pcp-tgu-service` | `spacecraftId`, `satellitePlanId`, `planStartTime`, `planEndTime`, `kppId` | process instance key persisted in `tracked_plan` | Exceptions from Camunda command propagate; manual/auto duplicate checks exist |
| Plan status update | `updatePlanStatus` | `pcp-tgu-service` | `satellitePlanId` | none | Missing/blank variable throws exception; worker completes after `planConfirmationService.confirm` |
| Satellite survey planning | `calculateSatelliteSurveyMissions` | `pcp-mission-planing-service` | `satellitePlanId`, `spacecraftId`, `planStartTime`, `planEndTime` | `modes` count | Risk: catch logs exception without explicit fail/rethrow |
| Satellite drop planning | `calculateSatelliteDropMissions` | `pcp-mission-planing-service` | `satellitePlanId` | `modes` count | Risk: catch logs exception without explicit fail/rethrow |
| Send satellite plan | `sendSatellitePlan` | `pcp-mission-planing-service` | `satellitePlanId` | publishes Camunda message `Message_SatellitePlanAccepted` | Risk: catch logs exception without explicit fail/rethrow; contains simulated acceptance delay |
| Update slots status | `updateSlotsStatus` | `pcp-mission-planing-service` | `satellitePlanId` | `slots` ids | Risk: catch logs exception without explicit fail/rethrow |

BPM domain-data observation:

- Не видно, что BPM/Zeebe является source-of-truth для доменных данных. Доменные состояния сохраняются в `pcp_tgu`, `pcp_missions`, `pcp_slots` и других сервисных БД.
- BPM variables содержат business identifiers и временные параметры. Это нормально как orchestration context, но не должно превращаться в master data.
- Риск не в том, что BPM явно хранит доменные данные, а в error handling workers и в неочевидной границе между TGU plan и mission-planning mission.

## 5. Data ownership map

| Data/domain concept | Owning service | Storage | Producers | Consumers | Notes |
|--------------------|----------------|---------|-----------|-----------|-------|
| Service configuration | `spring-cloud-config-server` / `config-repo` | YAML/git | developers/ops | all services | Infra config, not domain |
| Users/UI pages | `pcp-ui-service` | no domain DB | browser/controllers | browser | BFF only |
| Request | `pcp-request-service` | `pcp_requests.requests` | REST/Kafka `pcp.request.in.v1` | UI, slots, complex-plan, complex-mission | Source-of-truth |
| Request geometry remaining/coverage status | `pcp-request-service` | `requests`, `request_route_matches` | route matching | UI/downstream | Source-of-truth for request coverage by route |
| Earth grid cells | `pcp-request-service` | `earth_cells`, `earth_grid_settings` | grid init/import | request, slots, complex-mission | Source-of-truth inside PCP |
| Request-cell projection | `pcp-request-service` | `request_cells` | projection service | request/slots/complex | Projection/read model |
| Route passport normalized event | `pcp-route-processing-service` | Kafka only | external route source → route-processing | request, mission-planning | Stateless event transformation |
| Satellite catalog | `pcp-satellite-catalog-service` | `satellite` | catalog API | UI, slots, complex, TLE, TGU indirectly | Source-of-truth for satellite metadata |
| Satellite groups/profiles | `pcp-satellite-catalog-service` | group/profile tables | catalog API | UI, slots, complex | Source-of-truth |
| Stations | `pcp-stations-service` | `stations` | station API | UI, mission/coverage | Source-of-truth |
| Raw TLE | `tle-monitoring-service` | `pcp_tle.tle` | CelesTrak/manual API | ballistics via Kafka, TLE API | Source-of-truth for TLE |
| Orbit points / PDCM | `pcp-ballistics-service` | `pdcm` | TLE/IC processing | UI, complex-plan, coverage | Derived source-of-truth |
| Asc nodes | `pcp-ballistics-service` | `asc_node` | ballistics calculation | UI/clients | Derived |
| Flight line | `pcp-ballistics-service` | `flight_line` | ballistics calculation | complex-plan, UI, coverage | Derived |
| Earth coverage/cell covering | `pcp-ballistics-service` | `earth_coverage`, `cell_covering` | ballistics calculation | coverage/complex/UI | Derived/projection |
| Slots | `slots-service` | `slot` | slot calculation/init | UI, complex, mission | Source-of-truth for slots |
| Booked slots | `slots-service` | `booked_slot`, `booked_slot_request` | booking API, mission status events | UI, mission, complex | Source-of-truth for booking status |
| Satellite initial conditions | `slots-service` | `satellite_ic` | IC API | ballistics via Kafka | Source-of-truth for IC in slots context |
| Complex mission modes | `pcp-complex-mission-service` | `satellite_modes`, details | complex calculation | UI, mission-planning | Stateful planning result |
| Complex mission snapshots | `pcp-complex-mission-service` | `satellite_mode_snapshots` | snapshot/calculation | mission-planning/UI | Snapshot/read model |
| Legacy/main complex plan run | `pcp-complex-mission-service` | `complex_plan_run*` in `pcp_satellites` | `/api/com-plan/process` | UI/clients | Overlaps with new complex-plan service |
| New complex plan run | `pcp-dynamic-plan-service` | `pcp_complex_plan.complex_plan_run*` | `/api/v1/complex-plan/runs` | UI/API | Separate new context |
| Complex plan intervals/MPL candidates | `pcp-dynamic-plan-service` | interval/MPL tables | algorithms | reports/API | Derived artifacts |
| Coverage scheme calculation result | `pcp-coverage-scheme-service` | none | REST calculation | complex/UI | Transient unless persisted downstream |
| Missions/plans/modes | `pcp-mission-planing-service` | `missions`, `plans`, `modes`, survey/drop tables | REST/Camunda flow | UI/TGU/process | Source-of-truth for mission state |
| Mode ↔ booked slot relation | `pcp-mission-planing-service` and `slots-service` | `mode_booking` plus `booked_slot` | mission confirmation | mission/slots | Relation in mission DB; booking status source in slots DB |
| TGU tracked plan | `pcp-tgu-service` | `tracked_plan` | scheduler/manual/Camunda | TGU APIs/process | Source-of-truth for TGU plan lifecycle |
| Spacecraft planning state | `pcp-tgu-service` | `spacecraft_planning_state` | Kafka/external API | plan calculation | Projection/state from external points |

## 6. End-to-end business flows

### 6.1 TLE update → ballistics recalculation

1. `tle-monitoring-service` получает список спутников и проверяет TLE.
2. Если TLE нужно обновить, сервис загружает данные из CelesTrak.
3. TLE сохраняется в `pcp_tle.tle`.
4. Событие публикуется в Kafka topic `pcp.tle`.
5. `pcp-ballistics-service` потребляет событие TLE update.
6. Ballistics рассчитывает PDCM/orbit points, asc nodes, flight lines, coverage/cell covering.
7. Производные данные сохраняются в `pcp_ballistics`.
8. Downstream сервисы читают их через REST.

```mermaid
sequenceDiagram
    participant TM as tle-monitoring-service
    participant CT as CelesTrak
    participant K as Kafka pcp.tle
    participant B as pcp-ballistics-service
    participant DBT as pcp_tle
    participant DBB as pcp_ballistics

    TM->>CT: Load TLE
    TM->>DBT: Save raw TLE
    TM->>K: Publish TLE event
    K-->>B: Consume TLE event
    B->>DBB: Persist PDCM/flightline/coverage
```

Failure/retry notes:

- Если DB write и Kafka publish в `tle-monitoring-service` не атомарны, возможно сохранение TLE без события или событие без полного состояния.
- Ballistics processing should be idempotent by satellite/time/revolution, but constraints need direct review before relying on it.

### 6.2 Initial conditions from slots → ballistics recalculation

1. Пользователь/API создает или выбирает satellite IC в `slots-service`.
2. `slots-service` публикует `ICRVPlacedEvent`/`SatelliteICDTO` в `pcp.tle`.
3. `pcp-ballistics-service` фильтрует событие по type.
4. Ballistics пересчитывает производные орбитальные данные и сохраняет их.

```mermaid
sequenceDiagram
    participant S as slots-service
    participant K as Kafka pcp.tle
    participant B as pcp-ballistics-service
    participant DBB as pcp_ballistics

    S->>K: Publish ICRVPlacedEvent
    K-->>B: Consume IC event
    B->>DBB: Recalculate and persist derived orbit data
```

Risk:

- Topic name `pcp.tle` не отражает, что там также живут IC events.

### 6.3 Route passport → request coverage + mission mode status

1. Внешний producer отправляет route passport в `pcp.request.survey-georeference.v1`.
2. `pcp-route-processing-service` парсит JSON.
3. Сервис публикует route event в два topic:
   - `pcp.route.georeference.v1` для request-service;
   - `pcp.route.in.v1` для mission-planning.
4. `pcp-request-service` обрабатывает route geometry:
   - находит пересекающиеся заявки;
   - проверяет дедупликацию по `(request_id, route_id)`;
   - обновляет остаточную геометрию, match counters и status.
5. `pcp-mission-planing-service` обновляет status survey mode по route passport.

```mermaid
sequenceDiagram
    participant EXT as External route source
    participant RP as pcp-route-processing-service
    participant K1 as Kafka pcp.route.georeference.v1
    participant K2 as Kafka pcp.route.in.v1
    participant R as pcp-request-service
    participant M as pcp-mission-planing-service

    EXT->>RP: pcp.request.survey-georeference.v1
    RP->>K1: RouteGeoRefEvent
    RP->>K2: ModeStatusChangedEvent
    K1-->>R: RoutePassportDto
    R->>R: Match route with requests and update coverage
    K2-->>M: RoutePassportDto
    M->>M: Update survey mode status
```

Failure/retry notes:

- `pcp-route-processing-service` publishes to two topics. Without outbox, partial publish can cause request-service and mission-planning to disagree.
- Request-service has stronger deduplication for route matches than many other consumers.

### 6.4 Request + slots + booking

1. Заявка создается в `pcp-request-service` через REST или Kafka.
2. Request-service сохраняет request и projection to Earth grid.
3. `slots-service` получает request/grid data через HTTP.
4. `slots-service` рассчитывает candidate slots/coverage.
5. При booking создаются `booked_slot` и `booked_slot_request`.
6. UI/complex/mission flows читают booking state из slots-service.

```mermaid
sequenceDiagram
    participant U as UI/API
    participant R as pcp-request-service
    participant S as slots-service
    participant DBS as pcp_slots

    U->>R: Create/update request
    R->>R: Save request and grid projection
    S->>R: Load request/grid
    S->>S: Calculate slots/coverage
    S->>DBS: Save booked_slot and booked_slot_request
```

Failure/retry notes:

- Source-of-truth request остается в `pcp-request-service`; source-of-truth booking остается в `slots-service`.
- Mission/complex services should not treat local booked slot references as authoritative status.

### 6.5 Complex mission plan run via `pcp-complex-mission-service`

1. UI/API вызывает `/api/com-plan/process`.
2. Complex-mission получает request/grid from request-service.
3. Получает satellite/profile from satellite-catalog.
4. Запрашивает ballistics calculations.
5. Запрашивает slots/coverage and booking operations.
6. При необходимости вызывает coverage-scheme-service.
7. Сохраняет satellite modes, snapshots and complex plan run.
8. UI/mission-planning читает modes/snapshots.

```mermaid
sequenceDiagram
    participant UI as UI/API
    participant CM as pcp-complex-mission-service
    participant R as pcp-request-service
    participant C as pcp-satellite-catalog-service
    participant B as pcp-ballistics-service
    participant S as slots-service
    participant CS as pcp-coverage-scheme-service
    participant DBCM as pcp_satellites

    UI->>CM: POST /api/com-plan/process
    CM->>R: Load requests/grid
    CM->>C: Load satellites/profiles
    CM->>B: Load MPL/exact-time/cell coverage
    CM->>S: Load/book slots
    CM->>CS: Calculate coverage scheme
    CM->>DBCM: Persist modes/snapshots/run
    CM-->>UI: Run response
```

Failure/retry notes:

- This is a long synchronous orchestration chain.
- Compensation strategy for partial slot booking vs persisted complex mission state is not explicit in report-level scan.

### 6.6 New complex-plan run via `pcp-dynamic-plan-service`

1. Client calls `POST /api/v1/complex-plan/runs`.
2. Service creates run and stores run metadata.
3. It queries `pcp-request-service` for requests intersecting the interval.
4. It queries `pcp-ballistics-service` for flight line/MPL inputs.
5. It uses internal algorithms to build intervals and MPL candidates.
6. It persists artifacts in `pcp_complex_plan`.
7. Client can read run, result summary and GeoJSON intervals.

```mermaid
sequenceDiagram
    participant U as API/UI
    participant CP as pcp-dynamic-plan-service
    participant R as pcp-request-service
    participant B as pcp-ballistics-service
    participant DB as pcp_complex_plan

    U->>CP: POST /api/v1/complex-plan/runs
    CP->>DB: Create run
    CP->>R: Find requests by interval
    CP->>B: Load flight line / MPL inputs
    CP->>CP: Build intervals and candidates
    CP->>DB: Persist artifacts and result
    CP-->>U: Run response
```

Failure/retry notes:

- This flow has explicit persisted run status, which is good.
- It still depends on synchronous downstream calls.
- Its relation to legacy/main complex mission run must be clarified.

### 6.7 Mission planning + booked slot status update

1. Mission is created manually or by Camunda worker.
2. `pcp-mission-planing-service` loads satellite modes/snapshots from complex-mission.
3. It creates survey/drop modes and stores mission state.
4. On confirmation it determines booked slot IDs.
5. It publishes `BookedSlotsStatusChangedEvent` to `pcp.slots.status.v1`.
6. `slots-service` consumes the event and updates booked slot statuses.

```mermaid
sequenceDiagram
    participant M as pcp-mission-planing-service
    participant CM as pcp-complex-mission-service
    participant K as Kafka pcp.slots.status.v1
    participant S as slots-service
    participant DBM as pcp_missions
    participant DBS as pcp_slots

    M->>CM: Load modes/snapshot
    M->>DBM: Save mission/modes/booked slot refs
    M->>K: Publish BookedSlotsStatusChangedEvent
    K-->>S: Consume status event
    S->>DBS: Update booked_slot status
```

Failure/retry notes:

- Local mission DB stores relationships, but booking status authority is in slots-service.
- Without outbox, mission state update and Kafka publish are not guaranteed atomic.

### 6.8 TGU plan → Camunda process → mission workers

1. `pcp-tgu-service` receives/loads spacecraft points.
2. It calculates nearest plan and validates platform through classifier.
3. It registers tracked plan and starts Camunda process `createSatelliteMission`.
4. Camunda activates jobs in `pcp-mission-planing-service`:
   - calculate survey missions;
   - calculate drop missions;
   - send satellite plan;
   - update slots status.
5. Camunda activates `updatePlanStatus` in `pcp-tgu-service` to confirm tracked plan.

```mermaid
sequenceDiagram
    participant T as pcp-tgu-service
    participant CL as External classifier/API
    participant C as Camunda
    participant M as pcp-mission-planing-service
    participant DBT as pcp_tgu

    T->>CL: Validate platform / load points
    T->>DBT: Register tracked_plan
    T->>C: Start createSatelliteMission
    C-->>M: calculateSatelliteSurveyMissions
    C-->>M: calculateSatelliteDropMissions
    C-->>M: sendSatellitePlan / updateSlotsStatus
    C-->>T: updatePlanStatus
    T->>DBT: Mark tracked plan confirmed
```

Failure/retry notes:

- TGU worker error handling is clearer than mission-planning workers.
- Mission-planning workers should explicitly fail/rethrow after catch to let Camunda retry/fail jobs correctly.

## 7. API and message contracts summary

| Contract | Used by | Direction | Key fields | Purpose |
|----------|---------|-----------|------------|---------|
| `RequestDto` / request DTOs | request-service, UI, external Kafka producers, complex/slots | In/out | request id, interval, geometry, importance, coverage, status | Create/read/update requests |
| `RoutePassportDto` | route-processing, request-service, mission-planning | Kafka out/in | route id, geometry/time/status metadata | Route matching and mode status update |
| `KafkaMessage<T>` | route-processing, TLE, slots, mission | Kafka wrapper | type, data, metadata/correlation | Common event envelope |
| `PcpKafkaEvent` types | Kafka producers/consumers | Kafka headers/payload type | event type names | Consumer filtering/routing |
| `TLEDTO` | TLE monitoring, ballistics | Kafka/REST | satellite/NORAD, revolution, TLE lines/time | TLE update processing |
| `SatelliteICDTO` / IC DTOs | slots, ballistics | REST/Kafka | satellite id, IC/RVA coefficients | Initial condition placement |
| `BookedSlotsStatusChangedEvent` | mission-planning, slots | Kafka | bookedSlotIds, status, occurredAt, sourceService, missionId, modeId, satelliteId | Update booked slots status |
| `SpacecraftPointsMessage` | external/TGU producer, TGU | Kafka | spacecraftId, points/windows | TGU planning state update |
| `MissionRequestDTO` / mission DTOs | TGU/Camunda variables, mission-planning, UI | REST/Camunda | missionId/satellitePlanId, satelliteId, start/stop | Mission creation/planning |
| `ComplexPlanProcessRequestDTO` | UI/API, complex-mission | REST | satellites, interval, filters/options | Legacy/main complex plan run |
| `ComplexPlanRunStartRequestDTO` | clients, dynamic-plan-service | REST | NORAD/satellite, interval, options | New complex-plan manual run |
| `CoverageSchemeCalculateRequestDTO` | complex-mission/UI, coverage-scheme | REST | satellite/mode/geometry/time params | Coverage scheme calculation |
| Satellite catalog DTOs | UI, slots, complex, TLE | REST | satellite id, NORAD, profile params | Satellite metadata/profile contract |
| Station DTOs | UI, mission/coverage | REST | station number/name/location | Station lookup |
| Ballistics DTOs | UI, complex, coverage, TGU | REST | orbit/flightline/RVA/MPL fields | Derived ballistics data |

Breaking-change risks:

- `pcp-types-lib` centralizes many DTOs/events. This reduces duplication but also couples services to one shared library release.
- Kafka event type names and topic names are part of public contracts. Topic `pcp.tle` is overloaded by multiple event families.
- REST DTOs used by UI/BFF and orchestration services are effectively internal service contracts; no API versioning is visible for many legacy endpoints.

## 8. Architecture observations

### 8.1 Clear service boundaries

Good boundaries:

- Request ownership is mostly clear: `pcp-request-service` owns requests, request grid projection and route matches.
- Satellite catalog ownership is clear: `pcp-satellite-catalog-service` owns satellite metadata/profiles/groups.
- Ballistics ownership is mostly clear: `pcp-ballistics-service` owns derived orbital artifacts, not raw TLE.
- Slots ownership is clear for slot/booking source-of-truth.
- Stations ownership is clear.

Weak/unclear boundaries:

- `pcp-complex-mission-service` and `pcp-dynamic-plan-service` overlap on complex plan terminology and tables.
- Mission-planning stores `mode_booking` references while slots-service owns `booked_slot` status; this is acceptable as reference data, but status authority must remain explicit.
- Satellite identifiers/NORAD data appear across catalog, TLE, ballistics, slots, complex mission and TGU. Source-of-truth for metadata should remain catalog; derived/stored copies should be documented as snapshots/projections.

### 8.2 Data ownership conflicts

Potential conflict: `complex_plan_run` exists in both:

- `pcp-complex-mission-service` DB `pcp_satellites`;
- `pcp-dynamic-plan-service` DB `pcp_complex_plan`.

This may be valid if one is legacy and one is new, but the distinction must be explicitly documented in system docs and API naming. Otherwise engineers will not know which run is authoritative.

### 8.3 Tight coupling

- `pcp-dynamic-plan-service` has direct Gradle dependency on `:services:pcp-request-service`. This is a service boundary violation unless the dependency is only on shared DTOs/config that should be moved to `pcp-types-lib`.
- `pcp-ui-service` knows many backend endpoints and DTOs.
- Complex orchestration services call many downstream services synchronously.

### 8.4 Synchronous chains

The longest sync chains are:

- UI → complex-mission → request/catalog/ballistics/slots/coverage;
- UI → coverage-scheme → ballistics/complex-mission;
- complex-plan → request + ballistics + catalog;
- TGU → classifier/external API → Camunda → mission-planning workers.

Risks:

- cascading latency/timeouts;
- partial state update if one downstream call succeeds and later call fails;
- hard-to-reproduce failures without correlation IDs.

### 8.5 Kafka reliability and idempotency

Observed partial positives:

- Request route matching has uniqueness by `(request_id, route_id)`, giving real deduplication for route coverage.
- Slots DB has uniqueness for booked slot/cycle and booked slot/request links.
- TGU has duplicate/supersede logic for tracked plans.

Gaps:

- No consistent transactional outbox pattern found for DB write + Kafka publish.
- No clear DLQ policy in code.
- Kafka consumers generally depend on Spring Kafka error handling; service-level retry semantics are not consistently documented.
- Shared topic `pcp.tle` relies on event type filters.

### 8.6 BPM/Zeebe usage

Architecture standard expectation: BPM should orchestrate, while services own domain state. In this code:

- Domain state is in service DBs, not in BPM as far as static scan shows.
- BPM variables are IDs and timing context, which is acceptable.
- The weak point is worker error handling, especially in `pcp-mission-planing-service` where exceptions are caught/logged without explicit fail/rethrow.

### 8.7 Observability/correlation

- Route processing appears to preserve trace/correlation metadata in `KafkaMessage`/metadata.
- Complex-plan run stores `requestedBy` from proxy headers.
- There is no uniform evidence that all HTTP/WebClient calls propagate `correlation_id`/`trace_id`.

Recommendation: standardize `correlation_id` and `business_key` propagation across REST and Kafka.

### 8.8 Naming and maintainability

Naming issues:

- 
- `pcp-srpring-boot-admin-server` typo;
- `pcp-mission-planing-service` typo;
- package names sometimes reflect old service names;
- `pcp_request_service` package appears in ballistics context in inventory.

These are not just cosmetic: they make search, deployment, alerting and ownership mapping harder.

### 8.9 Dead/prototype code

`pcp-complex-mission-flow` exists in repository/config but is commented out in root `settings.gradle.kts`. Treat it as prototype or inactive until deployment confirms otherwise.

### 8.10 Schema/migration quality

Positive:

- Stateful services use Flyway migrations.
- JPA ddl-auto validation is used in configs.
- Important FK/unique constraints exist in request, slots, mission, catalog and complex-plan schemas.

Risk:

- Historical migration in TLE fixes Cyrillic `time_reс`; this suggests migration/schema reviews are important.

## 9. Questions this report can answer later

This Markdown should help answer questions such as:

- Какой сервис владеет заявками?
- Где хранится Earth grid?
- Кто публикует `pcp.route.georeference.v1`?
- Кто потребляет `pcp.route.in.v1`?
- Что происходит после загрузки TLE?
- Почему `pcp.tle` потребляет ballistics-service?
- Где хранится `booked_slot` и кто меняет его status?
- Как mission-planning сообщает slots-service о подтверждении слотов?
- Чем отличаются `pcp-complex-mission-service` и `pcp-dynamic-plan-service`?
- Где хранятся satellite modes и snapshots?
- Где хранятся complex-plan intervals/MPL candidates?
- Какой сервис отвечает за каталог спутников?
- Какой сервис отвечает за станции?
- Какие сервисы вызывает UI?
- Какие Kafka topics есть в системе?
- Какие Camunda workers реализованы?
- Хранит ли BPM доменные данные?
- Где потенциально нужен outbox/idempotency?
- Где есть риск tight coupling?
- Какие сервисы нужно изучить при изменении request coverage flow?
- Какие сервисы нужно изучить при изменении slot booking flow?
- Какие сервисы нужно изучить при изменении TGU satellite mission process?

## 10. Limitations

Этот отчет не заменяет исходный код полностью.

Нельзя надежно ответить только по этому отчету на вопросы:

- точная сигнатура каждого DTO field-by-field;
- все enum values и допустимые status transitions;
- точная математическая корректность алгоритмов ballistics/coverage/complex-plan;
- точные SQL constraints/indexes для каждого поля без открытия migrations;
- точный runtime behavior при конкретной ошибке Kafka/Camunda/HTTP;
- фактическая production topology, если Helm/K8s окружение отличается от config-repo;
- какие endpoints реально используются внешними клиентами;
- SLA/timeout/retry/DLQ настройки, если они задаются вне кода;
- security/authn/authz модель, если она вынесена в ingress/proxy;
- полная BPMN семантика без анализа BPMN diagrams/process definitions;
- поведение inactive/prototype модуля `pcp-complex-mission-flow` в runtime.

Для точных изменений реализации, bugfix, refactoring, SQL migration или контрактного изменения всё равно нужно открывать соответствующий сервисный код.

## Appendix A. Modules and shared libraries

| Module | Role |
|--------|------|
| `libs/pcp-types-lib` | Общие DTO, Kafka wrapper/events, request/satellite/ballistics/mission/contracts |
| `libs/ballistics-lib` | Баллистические/математические алгоритмы, используемые ballistics/coverage services |
| `config-repo` | Централизованные YAML configs |
| `docs/ci-cd-ballistics.md` | CI/CD notes для ballistics |
| `helm/*` | Deployment charts/values for selected services |

## Appendix B. Most important source paths

| Path | Why it matters |
|------|----------------|
| `settings.gradle.kts` | Shows active modules and commented `pcp-complex-mission-flow` |
| `config-repo/application-local.yaml` | Local ports, PostgreSQL and Kafka bootstrap |
| `config-repo/application-dev.yaml` | Dev service URLs and ports |
| `config-repo/<service>.yaml` | Service-specific DB/topic/downstream settings |
| `services/*/src/main/kotlin/**/controller` | REST entry points |
| `services/*/src/main/kotlin/**/service` | Business/orchestration logic |
| `services/*/src/main/kotlin/**/entity` | JPA storage ownership |
| `services/*/src/main/resources/db/migration` | Persistent schema and constraints |
| `libs/pcp-types-lib/src/main/kotlin` | Shared API/message contracts |
