После Postman demo audit — в cheatsheet не хватало живых примеров,
которые можно скопировать и сразу проверить. Добавил:
* FK-зависимость:
GET /dictionaries/satellite_type/dependents →
[{sourceDict: spacecraft, sourceField: satellite_type_code,
onClose: BLOCK, activeRecordsInSourceDict: 14}]
+ список других живых FK на staging (ground_station, country etc).
* Локализация записи через Accept-Language:
ru: НАСА / Глобальный мониторинг суши и атмосферы
en: NASA / Global land and atmosphere monitoring
+ warning что ?locale= игнорируется и schema endpoint вообще
не локализуется.
* Time-travel: 14.05.2026 12:00 → 200, 14.05.2026 00:00 → 404
record_not_active (ожидаемое поведение, не bug).
* History и changelog/diff живые примеры с test1.
Также убрал password-grant из Auth (используется client_credentials —
это правильный flow для server-to-server интеграторов). И добавил
dependents проверку в 60-second smoke.
Tested: GET /dictionaries/spacecraft с Accept-Language: en-US возвращает
schemaJson с descriptions на ru (defaultLocale). Header игнорируется на
этом endpoint.
Локализация (Accept-Language header) работает только на records-side
(read-api DictionaryReadController). DictionaryDefinitionController
(writer/ordinis-app) возвращает schema без locale negotiation.
Cheatsheet обновлён, добавлен warning в query-params секцию.
После testing на staging выявлено: backend парсит локаль ТОЛЬКО из
Accept-Language header. ?locale=en-US query param сейчас игнорируется
(сервер возвращает default ru-RU вне зависимости от значения).
Реальный demo (spacecraft/1999-068A):
default (без header): operator: "НАСА"
Accept-Language: en-US: operator: "NASA"
?locale=en-US (без header): operator: "НАСА" ← не работает
Cheatsheet + quickstart обновлены. Postman collection тоже (используется
header). ?locale= query — отдельный backend feature request в roadmap.
Status table в pending-endpoints.md обновлён: endpoints #1, #2, #4, #5
landed в MR !95-!98 в session 2026-05-11. Workflow API (#3) deferred —
требует отдельной design discussion + sprint (state machine + RBAC pool
model parallel to record-level DraftController architecture).
5 endpoints нужны admin-UI для завершения UI-фич:
1. GET /dictionaries/{name}/changelog — History tab + TimeTravel
2. GET /dictionaries/{name}/snapshots — TimeTravel slider marks
3. POST drafts/.../{review,decision,publish} — workflow state machine
4. PATCH /dictionaries/{name}/schema — Fields tab inline edit
5. GET /dictionaries/graph/outgoing — catalog → FK count column
Каждый endpoint содержит: purpose, route, query/body, response example,
errors, frontend integration estimate. Total frontend work after backend
ship — ~14h (1.5 sprint day).
OpenApiConfig:
- Добавлена OAuth2 security scheme (authorization_code flow с Keycloak
realm `nstart`). Auth/token URLs из ordinis.openapi.oauth.issuer-uri
configuration property (default: auth.nstart.space/realms/nstart).
- BearerAuth scheme сохранён secondary — для pre-issued tokens из CI/scripts.
- Servers list переупорядочен — prod первый, staging второй.
- Description обновлён с pointer на /docs/ для full integration guide.
application.yml:
- springdoc.swagger-ui.oauth: client-id (env override), use-pkce-with-
authorization-code-grant=true. Public client `ordinis-swagger`
настраивается отдельно в Keycloak — see keycloak-setup-swagger-client.md
в ordinis-infra repo.
- ORDINIS_OPENAPI_OAUTH_ISSUER_URI env var для override realm на разных
окружениях.
docs/integration/api/read-endpoints.md:
- Swagger UI section обновлён: акцент на Authorize button + Keycloak
PKCE login (no client_secret needed), tip про bearerAuth fallback.
docs/index.md:
- Добавлен tab "Я хочу пощупать API" с link на Swagger UI.
После deploy:
- https://ordinis.k8s.264.nstart.cloud/swagger-ui.html — Swagger UI
- https://ordinis.k8s.264.nstart.cloud/v3/api-docs — OpenAPI spec
Authorize → выбрать oauth2 → Keycloak login (PKCE) → Try it out с JWT.
Альтум-команда обнаружила что /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, +МСУ-ГСМ Арктики)