Commit Graph

48 Commits

Author SHA1 Message Date
Zimin A.N. 3365e9462a docs(toc): зарегистрировать quickstart + cheatsheet + регламент в Diplodoc nav
Файлы лежат в docs/integration/ с прошлых MR (!243, !247, !248), но в
toc.yaml не были включены — Diplodoc не строил их в /docs nav, и
пользователи могли попасть на них только по прямой ссылке.

Добавил три entries в секцию «Интеграция по API» сверху списка:
- 🚀 Quick Start (15 минут) → api-quickstart.md
- 📋 Cheat Sheet → api-cheatsheet.md
-  Регламент — что заводить в НСИ → dictionary-criteria.md

После merge ordinis-docs container пересоберётся, и в admin UI ссылка
"Docs" (top-right) откроет страницу с этими entries в left nav.
2026-05-20 19:09:51 +03:00
Zimin A.N. 20763feeb1 docs: HTML-вариант регламента «что заводить в НСИ»
Single-file standalone document (~23 KB). Embed CSS, no external deps.
Brand-consistent с PPTX/Postman — Warm Terracotta palette (#B05A2E),
Georgia headings + Inter body. Responsive (mobile breakpoint 640px),
print-friendly (page-break-inside на cards/tables).

Структура:
- Hero (dark navy + orange stripe + TL;DR callout)
- 5 положительных критериев (green left-border, ✓ glyph, hint boxes)
- 6 anti-patterns (pink left-border, ✗ glyph, symptom captions)
- 10-пунктный чек-лист (terracotta card, numbered orange circles)
- Процесс создания (3 секции × numbered steps)
- Schema conventions
- Final anti-patterns callouts
- Контакты footer

Use case: открыть в браузере, share через corp portal,
print PDF для офлайн-чтения. Markdown-версия остаётся для git-history
и в quickstart Приложение A.
2026-05-20 18:39:22 +03:00
Zimin A.N. 5b96f98fb8 docs(integration): регламент НСИ + текст рассылки для интеграторов
* dictionary-criteria.md — decision framework "что заводить в НСИ":
  - 5 положительных критериев (shared, slow change, validity windows,
    audit-trail, structured schema) с min-3-из-5 threshold
  - 6 anti-patterns (transactional, high-freq mutations, derived data,
    PII без ACL, BLOBs, single-consumer данные)
  - 10-пунктный чек-лист (≥7 yes → заводи, < — обсуди)
  - Процесс создания (simple + approval-required + миграция)
  - Schema conventions (businessKey, x-localized, x-references etc)
  - Anti-patterns с примерами из практики

* email-announcement.md — текст рассылки команде:
  - URLs (prod/staging/Swagger/docs)
  - Что внутри Ordinis (37 dicts, REST API, локализация, audit, workflow)
  - С чего начать (Quick Start, Cheat Sheet, Postman, presentation)
  - 60-second smoke командой
  - Roadmap Q3
  - Plain-text вариант для систем без markdown

Both files готовы к публикации: regulation идёт в integrator docs (link
из email), letter — в Mattermost / email-рассылку.
2026-05-20 17:10:03 +03:00
Zimin A.N. 5eecfdaad5 docs(quickstart): добавить Приложение A · Cheat Sheet
Cheatsheet был отдельным файлом — теперь дополнительно встроен в
api-quickstart.md как Приложение A. Reasoning:

* Single source — интегратор открывает quickstart один раз, дальше
  живёт в приложении (search в одном файле, не прыгает между двумя)
* Standalone api-cheatsheet.md сохранён для прямых ссылок и Postman README
* Section 13 обновлён: ссылка на Приложение + Postman collection
* Из appended body убраны self-references и дубликаты

Размер: 587 → 874 строк (+287 — cheatsheet body).
2026-05-20 13:50:55 +03:00
Zimin A.N. f3c3e33289 docs(cheatsheet): добавить конкретные примеры с реальными dicts
После 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.
2026-05-20 11:52:04 +03:00
Zimin A.N. ee4f495973 docs(api): уточнение — locale работает только на records, не на schema
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 секцию.
2026-05-20 11:46:41 +03:00
Zimin A.N. 11b6ca9835 docs(api): локализация — только Accept-Language header (не ?locale= query)
После 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.
2026-05-20 11:40:19 +03:00
Zimin A.N. ae05e17f96 docs(api): cheatsheet + quickstart sync с реальным API после Postman audit
Audit Postman collection выявил расхождения docs ↔ runtime — фикс:

Topology clarification:
- Records (consumer) — БЕЗ /dictionaries/ префикса: /api/v1/{name}/records
- History/cascade-preview/changelog/drafts — С /dictionaries/ (writer audit)
- export-selected.csv — POST, не GET

Query params (records list, /{name}/records):
-  as_scope (required, CSV) — было документировано как ?scope= (неверно)
-  at (ISO timestamp) — было ?asOf= (неверно)
-  locale + Accept-Language header
-  bbox / polygon (geo)
-  убраны: ?limit, ?offset (pagination отсутствует),
            ?status/?country (нет ad-hoc filtering по schema полям)

Snapshots params:
-  from / to / granularity (hour/day/week) — было ?asOf= (неверно)

Base URLs:
- prod: ordinis.nstart.cloud (public LE-cert)
- staging: ordinis.k8s.265.nstart.cloud (Swagger UI здесь)
- было: ordinis.k8s.264.nstart.cloud (устаревший internal, prod переехал)

Version: v2.36 → v2.37.x.

Refs MR !242 (snapshots backend fix), Postman collection в
~/Desktop/Ordinis-Postman/.
2026-05-19 23:15:40 +03:00
Александр Зимин 04e8251941 docs(api): Quick Start guide + Cheat Sheet для интеграторов 2026-05-17 13:14:33 +00:00
Александр Зимин a600664290 docs(changelog): fill 22-release gap v2.15.0 → v2.36.0 2026-05-17 09:15:07 +00:00
Zimin A.N. 8adfd39bff feat(bundle): bundle hygiene v2 — manifest spec + signing verifier + docs
Ships marketplace-design-v2 scoped to bundle hygiene (NO consumer UI, NO
install dialog, NO marketplace). 2-3 day cap respected — Approach C narrow
slice. Anti-feature commitment: scope creep → new design doc + /office-hours.

## What ships

### New module ordinis-bundle-spec
- BundleManifest.java — canonical apiVersion: ordinis.io/v1 record
  (Metadata + DictionaryEntry, Jackson-bindable, forward-compat ignoreUnknown)
- ManifestParser.java — YAML → record + structural validate
  (apiVersion/kind enforce, semver regex, bundle-id regex, path traversal
  guard на schemaRef, unique dict names, scope enum)
- BundleSignatureVerifier.java — ed25519 sign/verify (JDK 21 native)
- Zero Spring/JPA/Kafka deps — pure Java + Jackson YAML

### CUOD reference implementation
- ordinis-cuod-bundle/manifest.yaml — 40 dicts canonical entries
- Test fixture pin: cuod-manifest-fixture.yaml parses+validates clean
  (regression guard на каждом CI run)

### Tests
- 12 cases ManifestParser (happy + reject paths)
- 7 cases BundleSignatureVerifier (sign/verify roundtrip, tamper, wrong key)
- 1 case CUOD fixture pin
- Total 20 tests, all green

### Docs
- docs/integration/bundle-format-spec.md — formal spec для Java handoff
- docs/user-guide/bundle-authoring.md — how-to для новых bundle authors

## Why now (N=1 customer)

Per office-hours v2 decision: marketplace UI build = N customers value scale,
but bundle hygiene + sign format = AT N=1 ROI:
- Java team handoff requires documented spec независимо
- Sales demo «here's how customer #2 would ship custom bundle»
- Optionality для marketplace UI когда customer #2 LOI surfaces

## Explicitly NOT shipped (Phase 2 scope if ever)

- Publisher Maven plugin (separate artifact when actual publish needed)
- Browse catalog UI / install dialog (no customer #2 with use case)
- Dep resolution / topological install
- Multi-tenant Nexus namespacing
- Bundle uninstall flow
2026-05-17 10:39:07 +03:00
Александр Зимин c41e34545b docs(rbac): обновить RBAC sections после Phase 1d + Phase 2 2026-05-13 16:41:03 +00:00
Zimin A.N. 36c06ae1da feat(auth): WorkflowRoles configurable claim path + ordinis:admin super-role
User report: token has roles в resource_access.ordinis.roles (client-scoped),
backend WorkflowRoles читал hardcoded realm_access.roles → forbidden_role
для всех reviewer actions.

Backend:
- WorkflowRoles: depends OrdinisAuthProperties → reads via rolesClaim path
  (же что ScopeContext). Default realm_access.roles, на staging/prod env
  var ORDINIS_AUTH_ROLES_CLAIM=resource_access.ordinis.roles (уже wired
  в helm helper).
- Nested claim path resolver — mirror ScopeContext.readClaimByPath
- New super-role ADMIN ('ordinis:admin') — holder автоматически проходит
  любой workflow check без явного назначения отдельных ролей. Convenience
  для small teams.

Frontend (usePermissions.ts):
- tokenRoles() читает оба claim path (realm_access.roles +
  resource_access.ordinis.roles) и объединяет — UI gate работает
  независимо от backend config
- hasRole() recognizes 'ordinis:admin' как super-role override
- ROLE_ADMIN exported

Docs:
- docs/operator/rbac.md: добавлен ordinis:admin row, JWT claim path note,
  Admin profile updated (super-role vs composite explanation)
2026-05-13 13:17:54 +03:00
Zimin A.N. 1dba9476db docs(rbac): добавить матрицу realm-ролей Keycloak
operator/rbac.md — новая страница с полной матрицей RBAC:
- Scope ACL (ordinis:client:public/internal/restricted)
- Workflow роли (schema:reviewer, schema:publisher, record:reviewer)
- Action matrix (endpoint → required scope + role)
- Типичные профили (consumer, maker, reviewer, publisher, admin)
- Composite role 'ordinis:admin' для one-shot assignment
- Keycloak setup инструкция (Admin Console шаги)
- Диагностика типичных 403 ошибок

toc.yaml — link в раздел Руководство оператора.
operator/index.md, reviewer/index.md — cross-references к rbac.md.

Покрывает Phase 1d enforcement (MR !162) — пользователи теперь
знают какие роли назначать в Keycloak realm 'nstart'.
2026-05-13 12:47:50 +03:00
Александр Зимин e2080d8991 fix(docs,security): Swagger UI — staging для exploration, prod env-flagged 2026-05-12 17:43:12 +00:00
Александр Зимин 82e481a418 fix(docs): copy operator/reviewer/changelog dirs to docker image 2026-05-12 17:37:08 +00:00
Александр Зимин a34c6d4c82 feat(topbar): «Что нового» button + 2026-05-12 state.md update 2026-05-12 17:05:24 +00:00
Александр Зимин 58dd871808 Merge branch 'docs/marketplace-v2-bundle-hygiene' into 'main'
docs(design): marketplace v2 — bundle hygiene, hard cap 2-3d

See merge request 2-6/2-6-4/terravault/ordinis!147
2026-05-12 17:03:54 +00:00
Александр Зимин 89c6e04965 docs(design): marketplace v2 — bundle hygiene, hard cap 2-3d 2026-05-12 17:03:54 +00:00
Александр Зимин a3eb5f0c86 docs(design): ai-schema-assist v2 — /office-hours, Approach C hybrid 2026-05-12 17:03:52 +00:00
Александр Зимин cef5f49bf7 docs(design): AI schema assist + dictionary marketplace v1 proposals 2026-05-12 15:10:22 +00:00
Александр Зимин d9fc49fe72 docs(design): Redis FK projection v2 — eng review applied 2026-05-12 14:44:55 +00:00
Александр Зимин 5479142093 feat(webhook): time-series histogram stats endpoint + frontend chart 2026-05-12 14:30:22 +00:00
Александр Зимин 72268f9add feat(api): GET /changelog/{entryId}/diff — full before/after schemas 2026-05-12 08:51:28 +00:00
Александр Зимин d790a77313 docs(integrator): v2.x.x update — workflow API + full changelog + schema extensions 2026-05-12 00:26:37 +00:00
Zimin A.N. 6c8cc21204 docs(api): mark 4/5 pending endpoints shipped, workflow API deferred
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).
2026-05-11 23:15:41 +03:00
Zimin A.N. a4add2402a docs(api): pending-endpoints brief for backend team
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).
2026-05-11 22:47:24 +03:00
Zimin A.N. b96aad049f fix(docs/nginx): убрать try_files в unhashed fallback — alias bug
nginx с `alias` имеет известный bug: `try_files $uri` резолвит $uri от
document root, не от alias path. Для hashed assets (первое regex location)
try_files уже был убран ранее, но оставался в fallback unhashed location —
из-за этого `/docs/_assets/tabs-extension.js` (и .css) валились в 404
несмотря на наличие файлов в /usr/share/nginx/html/_assets/.

Теперь fallback просто alias'ит без try_files. Если файла нет — nginx сам
отдаст 404 от open() failure (нормальное поведение).
2026-05-08 09:22:15 +03:00
Zimin A.N. c24dec6a1f fix(docs): отдавать валидный empty sourcemap JSON вместо 204
DevTools пытается распарсить response как sourcemap JSON. 204 с пустым
body → `SyntaxError: JSON Parse error: Unexpected EOF` в console.

Решение: возвращаем минимально валидный sourcemap v3 с пустыми sources/
mappings — DevTools парсит, видит no-op, тихо проглатывает.
2026-05-08 09:10:35 +03:00
Zimin A.N. 11c9797757 feat(docs): вернуть YFM tabs syntax + bundle runtime assets
Diplodoc CLI 4.60 транформирует `{% list tabs %}` встроенным плагином,
но runtime assets (`_assets/tabs-extension.{js,css}`) НЕ копирует
автоматически — в отличие от mermaid/latex/page-constructor, у которых
bundle paths захардкожены в CLI.

Решение:
- добавил devDep `@diplodoc/tabs-extension@^3` (содержит runtime/)
- post-build `copy-tabs-runtime` script: копирует
  `build/runtime/index.{js,css}` → `_dist/_assets/tabs-extension.{js,css}`
- index.md: 4 секции "С чего начать" обёрнуты в `{% list tabs %}` —
  выглядит компактнее и интерактивнее чем плоский список заголовков

Verified локально: `yfm-tabs` HTML рендерится, assets в `_dist/_assets/`.
nginx fallback rule для `/docs/_assets/*` уже работает.
2026-05-08 09:09:51 +03:00
Zimin A.N. 425e5319db fix(docs): тихо отвечать 204 на .map запросы
Diplodoc CLI 4.60 не генерит sourcemaps, но оставляет
`//# sourceMappingURL=app.css.map` комментарии в JS/CSS bundles.
DevTools тянет .map файлы → 404 в console (6 ошибок на /docs/).

Nginx теперь возвращает 204 No Content для *.map под /docs/ —
DevTools тихо проглатывает, console зелёная.
2026-05-08 08:53:06 +03:00
Zimin A.N. 1d5ee4291e fix(docs): убрать YFM tabs syntax — extension не bundled by default
`{% list tabs %}` требует @diplodoc/tabs-extension package + plugin config,
не входит в base @diplodoc/cli build output. Без него HTML refs
/_assets/tabs-extension.{css,js} → 404 в browser console.

Convert на plain ### headers — same content, no missing assets, проще
для переводов и navigation.
2026-05-08 08:44:26 +03:00
Zimin A.N. ee509cd48b fix(docs/nginx): rewrite hashed bundle filenames + remove broken try_files
Diplodoc CLI 4.60 bug: HTML refs hashed asset names (например
`_bundle/app-34c68624e23be7ce.css`) но actual built _bundle/ contains
unhashed files (`app.css`). Browser получает 404 на все css/js
references → page broken.

Workaround в nginx — strip hash через regex location:
  ^/docs/(_bundle|_assets)/(.+?)-<hex8+>(\.<ext>)$
  → alias /usr/share/nginx/html/$1/$2$3

Также убран try_files который incorrectly matched $uri (URL path с hash)
вместо aliased file path → false 404.

Verified locally — 200 OK на:
  /docs/_bundle/app-34c68624e23be7ce.css
  /docs/_bundle/vendor-*.css
  /docs/_bundle/react-*.js
  /docs/integration/api/auth.html
2026-05-08 01:45:51 +03:00
Zimin A.N. 27648ee2f7 fix(ci): pnpm via npm install (skip corepack) — Dockerfile + build-docs job
Corepack может hang в CI runner на integrity-check либо non-TTY prompt
при первом activate. Заменяем на прямой npm install с pinned version
9.15.4 (latest stable v9, lockfile compat: lockfileVersion '9.0').

Изменения:
- ordinis-admin-ui/Dockerfile: corepack → npm install -g pnpm@9.15.4
- docs/Dockerfile: same swap
- .gitlab-ci.yml build-docs: same swap

Verified locally: docker build ordinis-admin-ui за 23 sec, no hang.
2026-05-08 00:35:41 +03:00
Zimin A.N. b601c4636f feat(swagger): OAuth2/Keycloak PKCE flow в Swagger UI + docs links
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.
2026-05-08 00:08:29 +03:00
Zimin A.N. cfe26a07a7 docs: Dockerfile + nginx + CI publish для deploy на ordinis.k8s.264.nstart.cloud/docs/
Multi-stage Dockerfile: yfm build (Node 20 alpine) → nginx 1.27 alpine
serving static HTML. Nginx config:
- /healthz endpoint для k8s probes
- /docs/ alias → /usr/share/nginx/html/ (Diplodoc делает relative links,
  alias корректно работает без URL rewriting)
- Hash-named assets (_bundle/) — cache 1y immutable
- HTML pages — cache 5min must-revalidate
- /docs (без trailing slash) → 301 → /docs/
- Security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy)

CI:
- build-docs (sanity check) — теперь только на non-main branches и MR
  (для preview без push). Production build идёт через docker-docs.
- docker-docs (NEW) — multi-stage Dockerfile build + push в repo.nstart.cloud
  через standard .docker_base + .publish_script pattern. Path-filtered на
  docs/**, manual через web UI.
- resolve-tag: emit RESOLVED_DOCS_TAG (= IMAGE_TAG, тот же что для backend).
- trigger-deploy-{staging,prod}: pass DOCS_IMAGE_TAG в downstream pipeline.

Local verify:
  cd docs && docker build -t ordinis-docs:test .
  docker run --rm -p 18088:8080 ordinis-docs:test
  curl localhost:18088/healthz       → 200
  curl -I localhost:18088/docs       → 301 → /docs/
  curl localhost:18088/docs/         → 200 index.html
  curl localhost:18088/docs/integration/api/auth.html → 200
  curl localhost:18088/docs/missing.html → 404

Соответствующие infra-side изменения (Helm chart docs deployment + Ingress
path /docs/, values, deploy script) — commit в ordinis-infra repo.
2026-05-07 23:44:03 +03:00
Zimin A.N. bcfb07f547 docs: split integrator guide (Diplodoc) vs internal docs + add build-docs CI
Чёткое разделение audiences:
- docs/ — consumer-facing only, Diplodoc-built. Public contract для
  интеграторов (Альтум, BI, third-party).
- docs-internal/ — operator runbooks, status snapshots, legacy tech pages.
  НЕ в Diplodoc build, НЕ публикуются.

Изменения:
- Move docs/{ops,status,tech} → docs-internal/{ops,status,tech}
- docs/toc.yaml: убраны секции Operations, Архитектура (legacy), Status
- docs/index.md: убран tab "оператор / on-call", focus на integrators
- docs/README.md: rewritten — scope только integrator guide, editorial
  guidelines (no leak internal architecture, stable API contract)
- .yfm: убран явный ignore status/* (теперь не нужно — папка переехала)
- docs-internal/README.md: index для внутренней документации с rationale
  разделения

Scrubbing implementation details из Diplodoc страниц:
- events.md: убраны Strimzi/cluster.142 references, OutboxPoller детали,
  internal alert names (OrdinisOutboxLagHigh, OrdinisOutboxDLQNonEmpty),
  metric names (nsi_outbox_*). Заменены на consumer-observable contract.
- webhooks.md: убраны metric names (nsi_webhook_ssrf_rejected_total),
  alert table (OrdinisWebhookHighFailureRate и т.д.). Retry policy
  переписана на user-side perspective.
- errors.md: убран alert name OrdinisReadApiErrorBudgetBurnFast, Tempo
  endpoint URL, internal connection details.
- x-references.md: OrphanReferenceScanner → general "Ordinis периодически
  детектирует". Убраны metric/alert names. Cascade roadmap без link на
  internal design doc.
- auth.md: убран file path ScopeContext.java.
- bundle-cuod.md: убран Maven module path.
- caching.md: cascade design link заменён на text reference.

CI:
- .gitlab-ci.yml: новый job build-docs (stage: build) — Node 20 alpine,
  pnpm install --frozen-lockfile + pnpm build, artifact docs/_dist на
  неделю. Triggers: auto на docs/**, либо manual web. Готов к follow-up
  pages-deploy job когда host решён.
- Новый pattern .docs-changes для rules.

Build verified clean: 13 HTML pages, 6.9M, no broken links/refs.
2026-05-07 23:27:03 +03:00
Zimin A.N. d5268b9395 docs: Diplodoc setup + полное руководство интеграции по API
Новая документация-as-code на платформе Diplodoc (Yandex open-source) с
YFM (Yandex Flavored Markdown). Build → static HTML, deployable куда угодно.

Что добавлено:
- package.json + .yfm + toc.yaml — Diplodoc setup, навигация для sidebar
- index.md — главная страница с tabs для разных audiences
- README.md — инструкция для contributors

Раздел integration/api/ — 11 страниц про интеграцию consumers:
- index — обзор + глоссарий
- auth — Keycloak service accounts, scope mapping
- read-endpoints — GET /dictionaries, list/by-key, spatial filters
- events — Kafka outbox топики, partition keys, idempotency, DLQ
- webhooks — HMAC, SSRF guard, retry policy, test ping endpoint
- bitemporal — validFrom/validTo + history, future-dated entries, bulk close/export
- x-references — FK syntax, validation errors, scope hiding, orphan scanner, v2 cascade preview
- caching — TTL / push / snapshot strategies, hybrid pattern
- errors — full error code reference (validation/auth/conflict/server), retry strategy
- best-practices — 33 numbered rules для consumers
- bundle-cuod — все 40 справочников с FK графом и сценариями

Обновлены:
- ops/README.md — link на новую integration/api/, убран inline <br>
- ops/slo.md — broken cross-repo links заменены на text references

Build:
  cd docs && pnpm install && pnpm build
  → ./_dist (20 HTML files, 7.1M)
  pnpm serve  # → http://localhost:8088

CI deploy job для GitLab Pages — в roadmap (см. docs/README.md).

Существующий tech/api-integration.md оставлен в toc как legacy
(содержимое мигрировано + расширено в integration/api/).
2026-05-07 23:19:02 +03:00
Zimin A.N. 0c79821f8e docs(roadmap): merge lineage + FK cascade в единый epic с design draft
Объединил два отдельных backlog item'а (Lineage / dependency graph + Cross-
dictionary FK с cascade rules) в один epic "Dictionary relationships v2" —
они complementary halves: lineage = read-side (discovery), cascade = write-side
(close semantics). Operate over same FK metadata, удобнее spec'ить вместе.

Design DRAFT 318 строк / 15KB:
- 3 stakeholder pain points (data stewards, Альтум consumers, schema editors)
- IN scope: A (lineage discovery 4 endpoints+UI), B (cascade rules block/warn/cascade), C (cross-cutting outbox+SLO)
- OUT scope (defer): schema-time validation, graph viz, multi-hop, cross-bundle
- 3 architecture options per area + recommendation (A=in-memory+MV hybrid, B=sync для v2)
- 4 D-questions для plan-eng-review
- 3 pre-code assignment items (Альтум behavior, UX preference, bundle versioning)
- 4-phase implementation (3-5 нед CC total)
- 4 risks + mitigations
- Success criteria с конкретными SLO targets
2026-05-07 23:05:18 +03:00
Zimin A.N. e307c15e27 docs(status): mark KafkaTopic orphan fix applied + k6-tests ConfigMap created
- Section "В процессе": KafkaTopics READY=False теперь struck-through, applied
  evening 2026-05-07 (все 3 topics annotated strimzi.io/managed=false, alerts
  больше не срабатывают, projection-writer connected).
- Section 0.1 artifacts: topic-orphan-fix.sh — added " applied" note inline.
- Section 0.1 artifacts: synthetic smoke pre-flight — отмечено что k6-tests
  ConfigMap уже создан, остаётся k6-keycloak-creds Secret (Keycloak SA
  client_secret) и apply CronJob + helm upgrade.
2026-05-07 23:01:25 +03:00
Zimin A.N. 6046c5aef6 docs(status): v1.0.1 — post-cutover hardening + image arch incident postmortem
Evening update к v1.0:
- SPOF на staging registry CLOSED (postgis-barman mirrored в repo.nstart.cloud:18.3-3.6.2-2)
- Monitoring artifacts ready (k6 prod variant, synthetic smoke + CronJob, 2 alerts)
- KafkaTopics READY=False janitorial fix (script ready)
- CI build job на 401 known-issue (manual fallback)

Section 0.1 добавлена с подробным postmortem image arch incident:
1. arm64 image из mac M-series попал в registry без --platform
2. kubelet cache на node удерживал stale arm64 layer под тем же тегом
3. Pod stuck Terminating 14 мин (CNPG gracePeriod=1800s)
Lessons закреплены в docker/postgis-barman/README.md (anti-footgun).
2026-05-07 22:53:32 +03:00
Zimin A.N. f0f84b1baa docs(status): v1.0 — production LIVE на cluster.142, Альтум переехал
Snapshot после Phase 1-5 production stand-up done:
- prod (cluster.142): LIVE, helm rev 22 на main-4252ad93, Альтум blue/green cutover завершён
- staging (cluster.265): теперь dev environment, не consumer-facing
- v0.9 → v1.0 anchor

Что задеплоено в prod (8 commits сегодня):
- bulk close + bulk export CSV
- audit URL persistence + chips
- pagination для records list (50/page)
- WebhookE2ETest re-enabled (no-op scheduler)
- 23 новых тестов

Operational artifacts (ordinis-infra):
- k8s/kafka/cluster-prod.yaml (Kafka recovery)
- scripts/vault/{setup,populate}.sh + README

Открытые items: KafkaTopics READY=False (orphaned),
postgis-barman image mirror в prod registry, k6 prod benchmark,
real ЦУОД data integration epic.

Approval workflow v2 deferred — design doc сохранён, re-evaluate
через 1-2 месяца после observed compliance needs.
2026-05-07 15:24:03 +03:00
Zimin A.N. 81c959b7e2 docs(status): snapshot v0.9 (2026-05-06)
Закрыло за сутки: bundle 7→40 справочников, Альтум pull verified,
Tempo+Loki+Grafana+SLO burn rate alerts (Google SRE multi-window),
UI scope grouping + accents, INTERNAL словари visibility (rolesClaim),
CNPG 1.24→1.25.4 + spec.probes, CI helm --atomic + auto-rollback,
config-server startupProbe, 75→109 unit тестов.

Готовы к prod (manifests + runbooks): multi-instance Postgres HA,
external S3 backup, k6 benchmark setup. Block — DNS/cert prod,
S3 provider creds, real ЦУОД data.

Прогресс: 21/33 (v0.5) → 27/39 требований (v0.9). 1-2 недели до v1.
v0.5 файл оставлен как историческая запись.
2026-05-06 13:27:31 +03:00
Zimin A.N. bcedddef71 docs(ops): SLO/SLI definitions + error budget framework
7 SLI с конкретными порогами и justification:
- read-api availability (99.5% v1 target)
- read-api p99 latency < 500ms target / 1s alert
- writer 5xx error rate < 1%
- outbox publish lag (≤ 50 normal, alert > 100)
- outbox DLQ size = 0 strict
- outbox publish error rate ~0
- postgres availability (99.9% v1 target)

Error budget framework для 99.5% уровня (~216 мин/мес downtime).
Burn rate alerts — TODO.

Notification routing — TODO (Slack/Telegram per severity).

Что не покрывает v1: Grafana dashboards, distributed tracing, log
aggregation, capacity planning. См. observability stack roadmap для v2.
2026-05-05 20:32:37 +03:00
Zimin A.N. adc40aca22 docs(ops): operator runbook — kafka, outbox DLQ, db migrations + index
Карточки процедур для on-call. Self-contained: можно открыть в момент
инцидента без необходимости понимать всю архитектуру.

- README.md — index by symptom + быстрые гайды по 401, 500, admin-ui 502.
- kafka-restart.md — pause/unpause, replicas=0 fix, force-delete, restart
  consumer'ов после Kafka up.
- outbox-dlq.md — диагностика DLQ через UI/API/SQL, типичные причины
  (orphan topic, ACL, broken payload), replay через UPDATE dlq_at=NULL.
- db-migrations.md — Liquibase changelog, добавление, откат, recovery
  failed migration через DELETE databasechangelog.

Vault unseal был отдельным коммитом ранее.
2026-05-05 17:26:30 +03:00
Zimin A.N. 0fb20dc8d4 docs(ops): vault unseal runbook + auto-unseal migration plan
Triage card для on-call: где взять unseal-keys (1Password placeholder,
уточнить с DevOps lead), как запустить script либо ручную процедуру,
что проверить после, troubleshooting типовых проблем.

Также: §7 — план миграции на auto-unseal (Transit / Yandex KMS) когда
определимся с master Vault или KMS-backend.
2026-05-05 16:56:45 +03:00
Zimin A.N. 2fc9b451e4 fix(cuod+docs): Resurs-P/Канопус/Метеор/Электро/Арктика в seed + правильный read-api путь
Альтум-команда обнаружила что /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, +МСУ-ГСМ Арктики)
2026-05-04 18:27:36 +03:00
Zimin A.N. 930df5b888 feat(api): Swagger UI + docs/integration для Альтума и других consumer'ов
Springdoc-openapi генерирует OpenAPI 3 spec из аннотаций контроллеров —
интеграторам не нужно поддерживать markdown-ТЗ синхронно с кодом.

- /swagger-ui.html (UI), /v3/api-docs (JSON), /v3/api-docs.yaml.
- OpenApiConfig: title/description/contact/servers (staging+prod+local),
  bearerAuth security scheme (Keycloak JWT).
- SecurityConfig: permitAll на swagger paths.

Документация:
- docs/integration/altum-imaging-order.md — ТЗ интеграции «Заказ съёмки».
  Согласованы: m2m service account через Keycloak, BFF в altum-backend
  (FastAPI), 4 справочника со схемами, cascading select через
  instrument.supported_*_codes, snapshot strategy для аудита.
- docs/tech/api-integration.md — общий гайд для интеграторов: auth flow,
  endpoints, кэш-стратегии, bitemporal модель, current dictionaries,
  cross-refs, best practices.

Скрипты codegen openapi-generator-cli работают off /v3/api-docs.
2026-05-04 15:45:09 +03:00