Был inline enum [PLANNED, ACTIVE, INACTIVE, DECAYED, LOST] — но
spacecraft_status справочник существует с нормализованными codes:
PLANNED, LAUNCHED, OPERATIONAL, STANDBY, DEGRADED, DECOMMISSIONED, LOST.
Теперь spacecraft.status = x-references на spacecraft_status.code.
Profit:
- i18n названий статусов (Запланирован/Эксплуатация/...)
- description per status (что значит DEGRADED vs DECOMMISSIONED)
- Расширяемо без schema migration
Breaking change: existing 14 records со status=ACTIVE/DECAYED не пройдут
validation. Решение: full re-import bundle на staging (TRUNCATE +
restart ordinis-app → CuodBundleStartupRunner пересоздаст все).
Демо нового x-references validator (commit 4142678).
До этого FK relationships были только в description как "FK на ...".
Теперь app-level integrity check на CRUD:
- spacecraft.satellite_type_code → satellite_type.code
- consumer.consumer_type → consumer_type.code
- deliverable_type.typical_processing_level → processing_level.code
- orbital_regime.parent_orbit_type → orbit_type.code
- antenna.ground_station → ground_station.code
Effect: POST/PUT записи с invalid FK → 422 ValidationError code
x_references_target_not_found, не silent broken reference.
Bundle version bumped 1.2.0 → 1.2.1 (breaking-change detection
прокатит — schemaVersion полей не менялись, только metadata).
Альтум-команда обнаружила что /api/v1/dictionaries/{name}/records даёт 500
и spacecraft_codes ссылаются на несуществующий "RESURS-P-3". Оба бага мои:
1. Read-api живёт на /api/v1/{name}/records (БЕЗ /dictionaries/ префикса).
/dictionaries/* — это admin-write контроллер, у него GET-list нет.
Fix: docs/integration/altum-imaging-order.md + docs/tech/api-integration.md
обновлены с правильными URL'ами + примером ответа из live staging.
2. spacecraft seed имел только 4 КА (Terra, Sentinel-1A/2A, Кондор-ФКА),
а mission.spacecraft_codes ссылался на пустые/RESURS-P-3 — каскад в
"Заказ съёмки" не работал бы.
Fix: добавлено 10 российских КА (Ресурс-П 1-4, Канопус-В 1+5, Метеор-М 2+2-2,
Электро-Л 2, Арктика-М 1) с COSPAR designators как businessKey.
3. mission.records.json + instrument.records.json: spacecraft_codes теперь
ссылается на реально существующие COSPAR-ключи. Каскад работает:
instrument MSU-MR → spacecraft [2014-037A, 2019-038A] → Метеор-М № 2 / 2-2.
После redeploy и идемпотентного пересева:
spacecraft 14 (было 4, +10 РФ)
mission 9 (existing 9, references фиксированы)
instrument 11 (было 10, +МСУ-ГСМ Арктики)
Importer бросал early-return для уже существующих definitions, поэтому
records никогда не наполнялись на повторных стартах. Records seed
теперь вызывается всегда (idempotent — skip по businessKey).
CuodBundleImporter теперь после создания DictionaryDefinition подгружает
records/<name>.records.json (relative to bundle resourceRoot) и создаёт
DictionaryRecord для каждой записи. Идемпотентно: пропускает business_key,
который уже существует.
Bundle:
- 5 satellite_type (SAR_X_HIRES, OPT_HIRES_VIS, OPT_MIDRES_MS, HYPER, METEO_GEO)
- 4 spacecraft (Terra, Sentinel-1A, Sentinel-2A, Кондор-ФКА №2)
- 3 ground_station (Отрадное, SvalSat, Байконур)
Все с локализованными name/description (ru-RU + en-US), валидируемые
JSON Schema на pre-save. Outbox events RecordCreated отправляются для
projection-writer.