Commit Graph

859 Commits

Author SHA1 Message Date
semantic-release-bot 2f06b408b8 chore(release): v2.37.0
## [2.37.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.36.0...v2.37.0) (2026-05-17)

###  Features

* **graph:** добавлен поиск по справочникам в Graph view ([d7de1eb](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/d7de1eb7404f3d51c61a01724a37a32a3e108203))

### 🐛 Fixes

* **admin-ui:** QA report sweep — modal/table layout, i18n, sidebar polish ([239cecd](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/239cecd2426480d3a2237c7961b56064a0e41346)), closes [#1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/1) [#2](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/2) [#3](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/3) [#4](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/4) [#5](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/5) [#6](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/6) [#7](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/7) [#8](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/8)

### 📝 Docs

* **changelog:** fill 22-release gap v2.15.0 → v2.36.0 ([a600664](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/a6006642900bfc34e37554994f5394e6ff39398e))
2026-05-17 12:45:50 +00:00
Александр Зимин 37c9ae7040 Merge branch 'fix/qa-report-sweep' into 'main'
fix(admin-ui): QA report sweep — modal/table layout, i18n, sidebar polish

See merge request 2-6/2-6-4/terravault/ordinis!239
2026-05-17 12:37:29 +00:00
Александр Зимин dd84e57030 Merge branch 'feat/graph-search' into 'main'
feat(graph): поиск по справочникам в Graph view

See merge request 2-6/2-6-4/terravault/ordinis!240
2026-05-17 12:37:06 +00:00
Zimin A.N. d7de1eb740 feat(graph): добавлен поиск по справочникам в Graph view
Top-left dark-glass input на странице /graph. Substring match
case-insensitive по name + displayName (admin помнит либо
technical id `antenna`, либо русское название `Антенны`).

UX:
- Matched nodes остаются в full opacity, остальные dim'ятся (0.25) —
  как при hover-focus. Force-layout не трогаем (positions стабильны).
- При единственном match → matched node получает focused border
  (orange accent + glow) — легко найти результат.
- Edges светятся только когда оба конца — match. Иначе dim.
- Counter chip `N из M` под input'ом + `ничего не найдено` для empty.
- Esc clears query и снимает focus. ✕-кнопка тоже clears (focus
  остаётся на input).
- Search dominates над hover dim — non-matched nodes остаются dim
  даже если hover их затрагивает.

i18n: graph.search.placeholder / .empty / .count для ru-RU и en-US.

Force-simulation не пересчитываем при изменении query — это намеренно.
Иначе nodes прыгали бы по экрану на каждый символ, ломая spatial
recognition (юзер уже привык где какой node лежит).
2026-05-17 15:36:06 +03:00
Zimin A.N. 239cecd242 fix(admin-ui): QA report sweep — modal/table layout, i18n, sidebar polish
Восемь дефектов из QA-отчёта одним MR.

#1 — Records-table теряла первую колонку после закрытия Create-modal.
Корень: lg:grid-cols-[220px_1fr] без minmax(0,…) — 1fr имел implicit
min-content (=max-content), позволяя table вырасти шире viewport.
После закрытия Radix Dialog снималось body padding-right (~15px), grid
пересчитывался и клиппил колонку под overflow-hidden card.
Fix: grid-cols-[220px_minmax(0,1fr)] + убран overflow-hidden с card
(Table primitive имеет свой overflow-x-auto).

#2 — Esc закрывал modal с задержкой (визуал/DOM рассинхрон).
duration-200 на slow CPU ощущался как несколько кадров между state=closed
и unmount. Снижено до duration-150 — совпадает с tw-animate-css дефолтами.

#3 — «+ Создать» обрезалось до «+ Соз» на ~1075px на detail-странице.
EditorTabBar: 6 tabs + 3 кнопки actions в одном flex row без shrink-0
давили друг друга. Решение: tabs в overflow-x-auto wrapper с min-w-0,
actions в shrink-0 контейнере — tabs скроллятся, actions всегда видны
полностью. scrollbar скрыт визуально (height-консистентность).

#4 — Обрезка названий в records-table при PUBLIC+INTERNAL.
Добавлен div.overflow-x-auto вокруг table + min-w-[760px] на table +
min-w-[180px] max-w-[320px] truncate на name cell. Catalog table также
получает min-w-[220px] на name column.

#5 — Заголовки колонок и кнопка «Граф» не локализованы на EN.
defaultValue:'Название' inline в коде падал на ru-text при EN locale.
Вынесены в i18n: dict.col.title/id/bundle/records/updated/outgoingFk/
incomingFk + dict.list.graph для обеих локалей.

#6 — Modal backdrop почти невидим.
bg-black/40 + 1px blur → bg-black/55 + 2px blur. Заметно темнее при
сохранении читабельности фона, фокус на modal.

#7 — Неестественная подсказка в форме «Создать»:
«Имя оставьте уникальное; версия сбросится на 1.0.0» →
«Укажите уникальное имя — версия сбросится на 1.0.0».

#8 — «Главная» в сайдбаре сбивала active state.
Клик на «Главную» вёл на `/` → redirect на /dictionaries → подсветка
уезжала на «Справочники». Logo сверху уже даёт home affordance, поэтому
duplicate nav item удалён (desktop + mobile).
2026-05-17 15:23:01 +03:00
Александр Зимин b56fcc41a4 Merge branch 'feat/phase-c-quiet-hours' into 'main'
docs(changelog): fill 22-release gap v2.15.0 → v2.36.0

See merge request 2-6/2-6-4/terravault/ordinis!238
2026-05-17 09:15:07 +00:00
Александр Зимин a600664290 docs(changelog): fill 22-release gap v2.15.0 → v2.36.0 2026-05-17 09:15:07 +00:00
semantic-release-bot 2fda3db547 chore(release): v2.36.0
## [2.36.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.35.0...v2.36.0) (2026-05-17)

###  Features

* **notifications:** Phase C — Don't Disturb (quiet hours window) ([74704db](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/74704dbf5b364fabacedcce66a8cce3b1ba2b28b))
2026-05-17 08:20:35 +00:00
Александр Зимин 2ca8f0530f Merge branch 'feat/phase-c-quiet-hours' into 'main'
feat(notifications): Phase C — Don't Disturb (quiet hours window)

See merge request 2-6/2-6-4/terravault/ordinis!237
2026-05-17 08:13:17 +00:00
Zimin A.N. 74704dbf5b feat(notifications): Phase C — Don't Disturb (quiet hours window)
User задаёт quiet window (e.g. 22:00–08:00 Europe/Moscow) — external
channels (email + express) DROP'аются dispatcher'ом. In-app bell badge
остаётся (юзер видит при следующем визите UI). Cross-midnight aware.

## Backend

- Migration 0026: user_notification_settings table (user_id PK + quiet_hours_start/end LocalTime + tz)
- Entity UserNotificationSettings + Repository (stock CRUD)
- UserPreferencesGate extended:
  - Constructor takes settingsRepo
  - allows() checks isQuiet(userId) первым for external channels (EMAIL/EXPRESS/TELEGRAM)
  - isQuiet: load settings → if hasEffectiveQuietHours() → check current LocalTime в user's TZ
  - inWindow() helper: cross-midnight semantics (22:00–08:00 wraps midnight)
  - Invalid TZ → fallback к DEFAULT_TZ (Europe/Moscow) с WARN log
  - Test seam: setClockForTesting(Clock) для deterministic tests
- MeNotificationsSettingsController: GET/PUT /api/v1/me/notifications/settings
  - HH:mm input parsing, IANA TZ validation, enabled=false clears window
  - Auth required (JWT sub claim)

## Frontend

- NotificationSettings type в client.ts
- useMyNotificationSettings query (60s stale)
- useUpdateNotificationSettings mutation
- QuietHoursSection в /me/notifications/preferences route:
  - Switch toggle + 2 time inputs + TZ select (12 RU/UTC zones)
  - Optimistic local state synced from query
  - Save button с pending/success/error states
- i18n RU + EN

## Tests

- 9 new tests UserPreferencesGateQuietHoursTest:
  - Same-day window match (inclusive start, exclusive end)
  - Cross-midnight window match (22:00–08:00)
  - No settings row → не блокирует
  - Quiet window active → email + express dropped
  - Outside window → email allowed
  - start == end → disabled (zero-duration treated as off)
  - Reviewer pool bypasses (always ON)
  - Invalid TZ → fallback default
  - Specific pref ON + quiet ON → quiet wins (drop)
- NotificationsDispatcherTest constructor updated к new signature
- Total notifications tests: 53 → 62, все green

## Design rationale (drop vs defer)

Drop chosen за defer (queue + re-fire scheduler) потому что:
- Defer needs persistent queue + scheduled retry — high complexity
- Most notifications time-relevant (draft N hours ago less actionable)
- Bell badge показывает full feed — ничего не «теряется»
- Phase D summary digest можно build later если demand surfaces
2026-05-17 11:11:21 +03:00
semantic-release-bot 6ed0b459de chore(release): v2.35.0
## [2.35.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.34.1...v2.35.0) (2026-05-17)

###  Features

* **bundle:** bundle hygiene v2 — manifest spec + signing verifier + docs ([8adfd39](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/8adfd39bff0e04017634f753c46ab9f7fc52f83d)), closes [#2](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/2) [#2](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/2) [#2](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/issues/2)
2026-05-17 07:48:10 +00:00
Александр Зимин 3cb6d419b9 Merge branch 'feat/bundle-hygiene-manifest' into 'main'
feat(bundle): bundle hygiene v2 — manifest spec + signing verifier + docs

See merge request 2-6/2-6-4/terravault/ordinis!236
2026-05-17 07:40:50 +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
semantic-release-bot f93751629b chore(release): v2.34.1
## [2.34.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.34.0...v2.34.1) (2026-05-16)

### 🐛 Fixes

* **nginx:** route /api/v1/ai/* к writer (был fall-through к read-api → 500) ([c86ce8c](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/c86ce8c8d5966470d38e0e88e6c138070c8c327b))
2026-05-16 16:56:21 +00:00
Александр Зимин c3c3693c7f Merge branch 'fix/nginx-route-ai' into 'main'
fix(nginx): route /api/v1/ai/* к writer

See merge request 2-6/2-6-4/terravault/ordinis!235
2026-05-16 16:51:26 +00:00
Zimin A.N. c86ce8c8d5 fix(nginx): route /api/v1/ai/* к writer (был fall-through к read-api → 500)
После !234 ship'нул AiSchemaController на writer, frontend hit /api/v1/ai/info
получает 500 — generic /api/v1/ location route к read-api который не имеет
этих handlers. Тот же pattern fix что для /drafts/, /me/, /admin/ — explicit
location к writer перед generic /api/v1/ fallback.

Без этого AI feature unusable в staging (даже если backend healthy).
2026-05-16 19:51:04 +03:00
semantic-release-bot 4b1293b845 chore(release): v2.34.0
## [2.34.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.33.0...v2.34.0) (2026-05-16)

###  Features

* **ai:** Phase 1 step 3-6 — LLM adapter + per-field AI suggest endpoint + UI ([e4cd7b9](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/e4cd7b9709da01c55cfba7f82107eec55f346b1d))
2026-05-16 16:32:52 +00:00
Александр Зимин ad69bc0fd6 Merge branch 'feat/ai-schema-suggest' into 'main'
feat(ai): Phase 1 step 3-6 — LLM adapter + per-field AI suggest endpoint + UI

See merge request 2-6/2-6-4/terravault/ordinis!234
2026-05-16 16:25:19 +00:00
Zimin A.N. e4cd7b9709 feat(ai): Phase 1 step 3-6 — LLM adapter + per-field AI suggest endpoint + UI
Approach C upgrade на templates foundation (!233). Admin может попросить AI
предложить новое поле — system prompt force'ит structural JSON Schema
fragment, admin review через accept/edit/reject. Bitemporal draft workflow
unchanged downstream.

## Backend
- `LlmAdapter` — OpenAI-compatible /v1/chat/completions client (Ollama,
  vLLM, OpenAI). Bean conditional на ordinis.ai.enabled=true.
- `AiSchemaService` — system prompt + 3 few-shot examples, JSON output
  parsing (с markdown fence stripping), validation (fieldName snake_case).
  In-memory circuit breaker: 10 fails в 60s → open 5 min.
- `AiSchemaController`:
  - GET /api/v1/ai/info → 200 (enabled) / 404 (disabled). Frontend probe.
  - POST /api/v1/ai/suggest-field → suggestion. Per-IP rate limit 30/min.
- All bean-conditional: ordinis.ai.enabled=false → controllers нет →
  endpoints 404 → frontend hides AI buttons automatically.

## Frontend
- `useAiFeatureAvailable` query — probes /ai/info, cache 5 min
- `useAiSuggestField` mutation — 30s timeout (LLM может быть slow)
- `AiFieldSuggestPanel` component — inline expandable: prompt → preview →
  accept/retry/reject. Error handling per HTTP status (503/429/422/502/404).
- DictionaryEditorDialog: AI toggle visible на schema tab когда
  aiAvailable=true. Accept wraps suggestion в mini-schema → parseSchemaJson
  (reuse existing kind-inference) → push в properties (overwrite если
  duplicate fieldName).
- i18n RU + EN

## Config
- application.yml: ordinis.ai.{enabled,endpoint,model,bearer-token,
  timeout-seconds}
- Helm writer.yaml: ORDINIS_AI_* env vars, optional secretRef для bearer
- values.yaml: ai.{enabled,endpoint,model,timeoutSeconds,bearerTokenSecretRef}
  defaults disabled

Pair с infra MR — values-staging enables AI с vortex.nstart.cloud Ollama
serving qwen2.5:7b.
2026-05-16 13:55:16 +03:00
semantic-release-bot db5d5c19e2 chore(release): v2.33.0
## [2.33.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.32.0...v2.33.0) (2026-05-16)

###  Features

* **schema:** Phase 1 schema templates + Nexus DevOps runbook ([c8dd5aa](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/c8dd5aad4e66e0181a7ff4192fc338be94467231))
2026-05-16 10:32:53 +00:00
Александр Зимин dfe1605552 Merge branch 'feat/templates-foundation' into 'main'
feat(schema): Phase 1 schema templates (Approach A) + Nexus DevOps runbook

See merge request 2-6/2-6-4/terravault/ordinis!233
2026-05-16 10:25:24 +00:00
Zimin A.N. c8dd5aad4e feat(schema): Phase 1 schema templates + Nexus DevOps runbook
## AI Schema Assist Phase 1 (steps 1-2)

Approach A core (templates only, no LLM) — admin начинает создание нового
справочника с curated skeleton вместо пустого Monaco. Approach C (per-field
LLM suggest) — Phase 2 на этом фундаменте.

### Backend
- `templates/*.template.json` в ordinis-cuod-bundle resources — 6 шаблонов
  (blank/spacecraft/ground-station/antenna/frequency-band/operator)
- `SchemaTemplateRegistry` (rest-api) — classpath scan at startup, strip
  x-template-* metadata, expose canonical JSON Schema
- `SchemaTemplatesController` — GET /api/v1/dictionaries/templates (list)
  + /{id} (detail с schemaJson)
- Cross-bundle support: scanner matches classpath*:templates/*.template.json
  — другие bundles могут shippит свои templates через те же conventions

### Frontend
- types: SchemaTemplateSummary + SchemaTemplateDetail
- queries: schemaTemplatesQuery + lazy detail query
- TemplatePicker.tsx — grid of cards (icon + name + description + tags),
  click → fetch detail → fire onPick(detail)
- Integrated в DictionaryEditorDialog (create mode, properties.length===0
  visible — после первой property picker исчезает чтобы не перезатереть)

## Nexus DevOps handoff

`docs-internal/ops/nexus-alpine-mirror.md` — runbook про APKINDEX vs file
inventory drift на v3.23 mirror. Includes:
- Verification commands
- 3 fix options (invalidate cache / scheduled refresh / self-host)
- Prometheus alert proposal
- Current workaround (node:22-alpine3.20 pin) reference

Active issue paired с CI saga !227/!229/!230 — нужен DevOps action.
2026-05-16 13:20:43 +03:00
semantic-release-bot 5821baa0f1 chore(release): v2.32.0
## [2.32.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.31.5...v2.32.0) (2026-05-16)

###  Features

* **records:** «Запланировано» badge per row для scheduled future versions ([e5a07fc](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/e5a07fc3919104cc73ab4519105360710d1f9992))
2026-05-16 09:59:28 +00:00
Александр Зимин 0b45ccbb2b Merge branch 'feat/scheduled-badge-per-row' into 'main'
feat(records): «Запланировано» badge per row для scheduled future versions

See merge request 2-6/2-6-4/terravault/ordinis!232
2026-05-16 09:52:00 +00:00
Zimin A.N. e5a07fc391 feat(records): «Запланировано» badge per row для scheduled future versions
Last item из QA report backlog'а. Banner + empty-state hint показывают
aggregate count, но не помогают find конкретные записи которые скоро
изменятся. Badge per row даёт O(1) visual scan.

Backend (read-api):
- ScheduledRecordsSummary.scheduledBusinessKeys: List<String> (capped 500)
- Repo method findScheduledBusinessKeys (DISTINCT subquery)
- Single fetch вместо N+1 per-row queries

Frontend:
- scheduledByKey Set<string> построен из summary
- Badge variant=info «Запланировано» рядом с businessKey badge'ом
- Title attribute с full RU/EN tooltip
- Не блокирует layout — gap-1.5 с pendingReview badge'ем (могут быть оба)

i18n keys для ru/en — short label «Запланировано» / «Scheduled».
2026-05-16 12:49:42 +03:00
semantic-release-bot dbbefe0510 chore(release): v2.31.5
## [2.31.5](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.31.4...v2.31.5) (2026-05-15)

### 🐛 Fixes

* **ui:** QA report P3/P4 batch — 7 cosmetic/UX bugs ([cb8a229](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/cb8a229adfaedcbf48466c0793a6c6e5c244d9df))
2026-05-15 21:15:32 +00:00
Александр Зимин d6ecd35140 Merge branch 'fix/qa-p3p4-batch' into 'main'
fix(ui): QA report P3/P4 batch — 7 cosmetic/UX bugs

See merge request 2-6/2-6-4/terravault/ordinis!231
2026-05-15 21:10:42 +00:00
Zimin A.N. cb8a229adf fix(ui): QA report P3/P4 batch — 7 cosmetic/UX bugs
QA report cleanup (после P1/P2 ship'нутых в v2.31.4):

- **BUG-009**: Excel/SQL export форматы получили явный «скоро» badge поверх
  opacity-only disabled state. Title attribute оставлен.
- **BUG-010**: «Доступ актора» (audit scope column) переименован в «Scope» —
  компактнее, не переносится на 2 строки.
- **BUG-011**: Все audit table headers получили title attribute → hover
  tooltip когда text truncate'ится («ИЗМЕНЕН…» → full «Изменения»).
- **UX-001**: Scope chips в /dictionaries теперь показывают ✓ glyph когда
  selected → визуально clear что multi-select. Aria-label расширен:
  «Фильтр по области (можно выбрать несколько)».
- **UX-002**: Breadcrumb segments получили title attribute → hover показывает
  full label когда truncate'ится в narrow viewport.
- **UX-003**: При смене вкладки в редакторе справочника (records → relations
  и т.п.) URL params q/scopes сбрасываются — раньше search фильтр оставался
  применённым после возврата на records.
- **UX-004**: TimeTravel slider boundary метки получили 2-digit year:
  «05.05.26» вместо «05.05» — disambiguates конец декабря / начало января.
  Title attribute exposes full локальную дату.
- **UX-009**: «Удалить» button в RecordDrawer переименован в «Закрыть запись»
  — same action как row context menu «Закрыть» (bitemporal close, не truly
  delete). Consistent labeling across UI.
2026-05-16 00:09:41 +03:00
semantic-release-bot 55ac362a11 chore(release): v2.31.4
## [2.31.4](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.31.3...v2.31.4) (2026-05-15)

### 🐛 Fixes

* **ci:** apk update before add — picks current package versions from mirror ([fc31963](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/fc3196349c80357d16a5761e64087a4ea92c9372))
* **ci:** apk использует internal Nexus mirror вместо public Alpine CDN ([1e0c49f](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/1e0c49fd6936c175811c5f11c4e0130122b889de))
* **ci:** pin release job к node:22-alpine3.20 — bypass v3.23 mirror APKINDEX bug ([ca48ff7](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ca48ff7f421eadd0cd3c740307f446a51a73ecf7))
* **search:** scope filter uppercase — fixes Smart Search 0 results bug ([35147df](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/35147df68336b872ea65151c913e70baba646a9c))
2026-05-15 20:21:08 +00:00
Александр Зимин 468a732bad Merge branch 'fix/ci-pin-alpine-version' into 'main'
fix(ci): pin release job к node:22-alpine3.20 — bypass v3.23 mirror bug

See merge request 2-6/2-6-4/terravault/ordinis!230
2026-05-15 20:14:38 +00:00
Zimin A.N. ca48ff7f42 fix(ci): pin release job к node:22-alpine3.20 — bypass v3.23 mirror APKINDEX bug
Nexus Alpine v3.23 APKINDEX рассинхронизирован: claims ca-certificates-20251003,
но в file storage только -20260413. Same для libexpat (claims 2.7.3, files 2.7.5).
Apk add 404. v3.20 mirror — consistent.

`node:22-alpine` (latest) использовала Alpine 3.23 → broken. Pin к
`node:22-alpine3.20` обходит баг — apk видит matching versions и files.
2026-05-15 23:14:17 +03:00
Александр Зимин be224e14b8 Merge branch 'fix/ci-apk-update-before-add' into 'main'
fix(ci): apk update before add — picks current package versions from mirror

See merge request 2-6/2-6-4/terravault/ordinis!229
2026-05-15 20:04:58 +00:00
Zimin A.N. fc3196349c fix(ci): apk update before add — picks current package versions from mirror
Image приходит с pre-cached APKINDEX (старые package versions с момента
build'а image). После repo swap (sed на internal mirror) apk всё ещё
использовал stale cache — просил ca-certificates-20251003 когда в mirror
только 20260413 → HTTP 404.

Fix: explicit `apk update` после sed, перед `apk add`. Это refresh'ит
APKINDEX с нашего mirror; apk теперь видит actual available versions.

Применено к 3 jobs (commit-msg-lint, build-docs prep step внутри release,
propose-prod-image-bump). После этого release должен пройти на следующем
main pipeline → semantic-release минтит v2.31.4 → propose-prod-image-bump
auto-создаст infra MR без manual intervention.
2026-05-15 23:04:25 +03:00
Александр Зимин 5916f0baec Merge branch 'fix/smart-search-scope-uppercase' into 'main'
fix(search): scope filter uppercase — fixes Smart Search 0 results (BUG-005)

See merge request 2-6/2-6-4/terravault/ordinis!228
2026-05-15 19:52:24 +00:00
Zimin A.N. 35147df683 fix(search): scope filter uppercase — fixes Smart Search 0 results bug
QA report BUG-005: "/search" возвращал 0 результатов на любые запросы
(«антенна», «GS_MOSCOW», «super» — всё пусто).

Root cause: SearchController convertedil scope enum в lowercase перед
WHERE filter:
  data_scope = ANY(CAST(? AS TEXT[]))  -- value: 'public'

Но DB stores UPPERCASE per migrations 0008/0009 CHECK constraint:
  CHECK (data_scope IN ('PUBLIC', 'INTERNAL', 'RESTRICTED'))

Filter 'public' никогда не матчил 'PUBLIC' → empty result для всех queries.
Багу 5+ месяцев — comment в коде утверждал что DB lowercase, что было
неправдой даже в момент написания.

Fix: убрать .toLowerCase() — pass enum names как есть. Verified:
  curl /api/v1/antenna/records?as_scope=PUBLIC возвращает GS_MOSCOW_A1
  но curl /api/v1/search?q=GS_MOSCOW возвращал 0. После fix должен матчить.
2026-05-15 22:51:01 +03:00
Александр Зимин ba9eeac53b Merge branch 'fix/ci-alpine-internal-mirror' into 'main'
fix(ci): apk использует internal Nexus mirror вместо public Alpine CDN

See merge request 2-6/2-6-4/terravault/ordinis!227
2026-05-15 19:35:39 +00:00
Zimin A.N. 1e0c49fd69 fix(ci): apk использует internal Nexus mirror вместо public Alpine CDN
Runner не имеет outbound к dl-cdn.alpinelinux.org (Permission denied):
```
WARNING: fetching https://dl-cdn.alpinelinux.org/alpine/v3.20/main: Permission denied
ERROR: unable to select packages: curl, git, jq (no such package)
```

Это сломало propose-prod-image-bump в v2.31.3 tag pipeline (failed) — пришлось
вручную создавать infra MR. Тот же риск висел над commit-msg-lint и build-docs.

Fix: sed-замена /etc/apk/repositories на `repo.nstart.cloud/repository/alpine`
перед каждым apk add. Probe подтвердил что mirror отвечает 200 на
`/repository/alpine/v3.20/main/x86_64/APKINDEX.tar.gz`.

Touches: 3 Alpine-based jobs (commit-msg-lint, build-docs, propose-prod-image-bump).
2026-05-15 22:34:47 +03:00
semantic-release-bot 38761947a2 chore(release): v2.31.3
## [2.31.3](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.31.2...v2.31.3) (2026-05-15)

### 🐛 Fixes

* **qa-report:** version tag, /drafts redirect, audit filter complete, i18n cleanup ([ff7e72e](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ff7e72e0fd3df32f96a39965a4832efa6602b080))
2026-05-15 19:13:22 +00:00
Александр Зимин 57a2341cc9 Merge branch 'fix/qa-report-i18n-batch' into 'main'
fix(qa-report): version tag display, /drafts redirect, audit filter, i18n cleanup

See merge request 2-6/2-6-4/terravault/ordinis!226
2026-05-15 19:04:29 +00:00
Zimin A.N. ff7e72e0fd fix(qa-report): version tag, /drafts redirect, audit filter complete, i18n cleanup
QA report v2.31.x batch:

- **VersionController.tag**: было 'none' (maven build на main без git tag) → UI
  показывал «dev · 6077d4df». Helm передаёт image.tag через env
  ORDINIS_BUILD_IMAGE_TAG, controller парсит «v2-31-2-e3c82775» → «v2.31.2».
  Helm chart change в ordinis-infra (separate MR).

- **/drafts redirect** (BUG-003): пустой 404 «Not Found» plain text → теперь
  static redirect на /my-drafts.

- **Audit action filter** (BUG-004): дропдаун содержал только 3 значения
  (CREATE/UPDATE/CLOSE), но в таблице 11 типов (DRAFT_*, DEFINITION_*).
  Frontend AuditAction enum + ACTIONS list синхронизированы с backend
  AuditLogger/SchemaDraftService/DraftService.

- **i18n cleanup** (BUG-006/007/UX-005):
  - myDrafts.description: «Все ваши submissions с pending/approved...» →
    «Все ваши черновики с историей: ожидает рассмотрения, одобрен...»
  - reviews.description: «Pending drafts от makers, ждут approve/reject» →
    «Черновики от авторов, ждут одобрения или отклонения. Общая очередь...»
  - reviews.queueTotal: «N pending drafts» → «N черновиков в очереди»
  - myDrafts.col.reviewer: «Reviewer» → «Рецензент» (RU only)
  - notifications chip labels: 'submit/approved/rejected' → 'отправлен/
    одобрен/отклонён'
  - audit.action.* expanded к 13 entries для каждого backend action
    type, с понятными лейблами «Черновик одобрен» вместо «DRAFT_APPROVE»

- **WhatsNewModal markdown** (UX-006): тексты вроде «**График доставки
  webhook'ов**» рендерились с буквальными звёздочками. Mini inline renderer
  для **bold**, *italic*, `code` — без full markdown library.
2026-05-15 22:02:29 +03:00
semantic-release-bot e3c827752e chore(release): v2.31.2
## [2.31.2](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.31.1...v2.31.2) (2026-05-15)

### 🐛 Fixes

* **record-form:** prefill validFrom=now в create mode тоже ([a740ab3](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/a740ab32bffe17c13e394534ac1860bf5b68be1d))
* **records:** scheduled marks on time-travel + non-empty banner + editor validFrom prefill ([9199f38](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/9199f380e1c52ab49384bb5813b38108e34a4ac8))
* **timetravel:** drop arbitrary +30d max — use real marks only ([d0ef822](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/d0ef822b9e2efb35dc8f63496a8e3da9521d0a4b))
2026-05-15 18:41:53 +00:00
Александр Зимин 6077d4dfe8 Merge branch 'fix/create-form-validfrom-prefill' into 'main'
fix(record-form): prefill validFrom=now в create mode тоже

See merge request 2-6/2-6-4/terravault/ordinis!225
2026-05-15 18:34:18 +00:00
Zimin A.N. a740ab32bf fix(record-form): prefill validFrom=now в create mode тоже
Form review после !224 показал что create mode имеет тот же баг что и edit:
SchemaDrivenForm без переданного defaultValues fallback'ит на '' для
validFrom, и пользователь видит пустое поле «Действует с».

Добавлен defaultValues={{ validFrom: nowIsoLocal() }} для create — consistent
UX с edit mode (!224 fix). Other formы (drafts, reviews, schema workflow) —
либо read-only либо без validFrom, clean.
2026-05-15 21:32:41 +03:00
Александр Зимин a996b1d4e8 Merge branch 'fix/scheduled-marks-banner-prefill' into 'main'
fix(records): scheduled marks + non-empty banner + editor validFrom prefill

See merge request 2-6/2-6-4/terravault/ordinis!224
2026-05-15 18:30:30 +00:00
Zimin A.N. d0ef822b9e fix(timetravel): drop arbitrary +30d max — use real marks only
User feedback: «крайняя дата должна быть исходя из реальной в этом
словаре». Раньше slider всегда extended до now + 30d даже без причины —
если нет scheduled записей на 18.05, slider всё равно тянулся туда,
пользователь блуждал по пустоте.

Теперь max = max(marks) — last real change point (record validFrom включая
upcoming scheduled, которые backend возвращает в /scheduled-summary).
Если все marks в прошлом — max=now (always reachable). Если есть future
scheduled на 18.05 — slider тянется ровно туда, не дальше.

Touches: TimeTravelPicker.tsx (inline editor) + TimeTravelModal.tsx (modal).
2026-05-15 21:30:08 +03:00
Zimin A.N. 9199f380e1 fix(records): scheduled marks on time-travel + non-empty banner + editor validFrom prefill
Три связанных UX бага после v2.31.0 release:

1. **TimeTravel marks**: после !220 slider extended до now+30d, но отметок в
   future window не было → blind drag. Backend теперь возвращает
   upcomingValidFroms (top 50) в /scheduled-summary; frontend merges как marks.

2. **Non-empty banner**: empty-state hint работает только когда список пуст.
   Если currently active записи есть AND ещё запланированы — пользователь
   не видит. Добавлен info banner над таблицей с тем же текстом + CTA.

3. **Editor "Действует с"**: edit mode оставлял поле пустым (bitemporal
   policy «новая версия с now»). User feedback: «показывает ничего, а даты
   заданы» — выглядит как баг. Prefill nowIsoLocal() — теперь юзер видит
   конкретную дату как точку отсчёта.
2026-05-15 21:28:29 +03:00
semantic-release-bot a800d56afa chore(release): v2.31.1
## [2.31.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.31.0...v2.31.1) (2026-05-15)

### 🐛 Fixes

* **timetravel:** extend modal slider max до now + 30 days (paired с !220) ([1713951](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/1713951f76f02df46a3b470e525d2ec9d79f9545))
2026-05-15 18:13:46 +00:00
Александр Зимин 24ac9fd33a Merge branch 'fix/timetravel-modal-future-window' into 'main'
fix(timetravel): extend modal slider max до now + 30 days (paired с !220)

See merge request 2-6/2-6-4/terravault/ordinis!223
2026-05-15 18:08:45 +00:00
Zimin A.N. 1713951f76 fix(timetravel): extend modal slider max до now + 30 days (paired с !220)
MR !220 расширил range у TimeTravelPicker.tsx, но юзер видит другой компонент —
TimeTravelModal.tsx (fullscreen modal с компарисоном now vs picked moment).
У него своя range logic с max = now + pad (1 day), и фикс !220 туда не дотянулся.

User feedback: создал запись с validFrom=18.05, открыл time-travel modal — слайдер
14.05 → 16.05, не дотянуть до 18-го.

Apply same 30-day future window logic к TimeTravelModal так чтобы оба компонента
вели себя одинаково.
2026-05-15 21:08:02 +03:00
semantic-release-bot d728d4f2fd chore(release): v2.31.0
## [2.31.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.30.1...v2.31.0) (2026-05-15)

###  Features

* **records:** scheduled records empty-state hint ([2341846](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/234184645f235680e43b49d8a6cb5e41946db088))
2026-05-15 17:54:56 +00:00