Commit Graph

830 Commits

Author SHA1 Message Date
semantic-release-bot c866a68f06 chore(release): v2.27.1
## [2.27.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.27.0...v2.27.1) (2026-05-14)

### 🐛 Fixes

* **e2e:** disable notifications dispatcher in test profile ([5e10bbb](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/5e10bbb6bb08ab6a6015efe8c66acbbdcc5cdaa4))

### 📝 Docs

* **design:** DESIGN.md v1 — resolve Section 12 open items ([7bd4b0a](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/7bd4b0ad7e002c63637288abf8830f4a61acd2e2))
2026-05-14 15:28:10 +00:00
Александр Зимин 06d3028977 Merge branch 'docs/design-policies-section-12-resolution' into 'main'
docs(design): DESIGN.md v1 — resolve Section 12 open items

See merge request 2-6/2-6-4/terravault/ordinis!192
2026-05-14 15:21:58 +00:00
Александр Зимин 7bd4b0ad7e docs(design): DESIGN.md v1 — resolve Section 12 open items 2026-05-14 15:21:58 +00:00
Александр Зимин 84dd19a3c3 Merge branch 'fix/e2e-notifications-disable' into 'main'
fix(e2e): disable notifications dispatcher in test profile

See merge request 2-6/2-6-4/terravault/ordinis!191
2026-05-14 15:21:56 +00:00
Александр Зимин 5e10bbb6bb fix(e2e): disable notifications dispatcher in test profile 2026-05-14 15:21:56 +00:00
semantic-release-bot 2b7a758e68 chore(release): v2.27.0
## [2.27.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.26.1...v2.27.0) (2026-05-14)

###  Features

* **notifications:** TODO 7 — draft decision toast + email + bell badge ([9050e24](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/9050e2427e0fe85f84ca38f1bbe67f1cd9344acf))

### 📝 Docs

* **todos:** mark all session TODOs shipped + summary table ([14f58b4](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/14f58b49276d7c97a545bca16f140fcf39d61990))
2026-05-14 14:50:58 +00:00
Zimin A.N. 14f58b4927 docs(todos): mark all session TODOs shipped + summary table 2026-05-14 17:41:54 +03:00
Александр Зимин 35b790f975 Merge branch 'feat/notifications-fullstack' into 'main'
feat(notifications): TODO 7 — draft decision toast + email + bell badge

See merge request 2-6/2-6-4/terravault/ordinis!190
2026-05-14 14:40:35 +00:00
Александр Зимин 9050e2427e feat(notifications): TODO 7 — draft decision toast + email + bell badge 2026-05-14 14:40:35 +00:00
semantic-release-bot 50d263745a chore(release): v2.26.1
## [2.26.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.26.0...v2.26.1) (2026-05-14)

### ♻️ Refactoring

* **reviews:** interaction state polish — 5 UX fixes ([fb64ca4](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/fb64ca4350d2d7581a13e8453158ef80a4592d72))
2026-05-14 14:22:44 +00:00
Александр Зимин e661719869 Merge branch 'refactor/reviews-interaction-polish' into 'main'
refactor(reviews): interaction state polish — 5 UX fixes

See merge request 2-6/2-6-4/terravault/ordinis!189
2026-05-14 14:13:57 +00:00
Александр Зимин fb64ca4350 refactor(reviews): interaction state polish — 5 UX fixes 2026-05-14 14:13:57 +00:00
semantic-release-bot 513b57b6b5 chore(release): v2.26.0
## [2.26.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.25.1...v2.26.0) (2026-05-14)

###  Features

* **reviews:** "Мои" tab — maker self-tracking with status filter ([be58b61](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/be58b6191383e0cecd9c2a06ef99b1835ecd3dce))
2026-05-14 14:11:18 +00:00
Александр Зимин 96589be33f Merge branch 'feat/reviews-mine-tab' into 'main'
feat(reviews): "Мои" tab — maker self-tracking with status filter

See merge request 2-6/2-6-4/terravault/ordinis!188
2026-05-14 14:06:30 +00:00
Александр Зимин be58b61913 feat(reviews): "Мои" tab — maker self-tracking with status filter 2026-05-14 14:06:30 +00:00
semantic-release-bot a6a07428ed chore(release): v2.25.1
## [2.25.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.25.0...v2.25.1) (2026-05-14)

### ♻️ Refactoring

* **approval-ux:** eng-review fixes — extract helpers, add tests, register i18n ([4c29f4e](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/4c29f4e7cbab6be552603f7791f1de35a882cb71))
2026-05-14 13:57:00 +00:00
Александр Зимин c6f8f095b1 Merge branch 'refactor/approval-ux-eng-review-fixes' into 'main'
refactor(approval-ux): eng-review fixes — extract helpers, add tests, register i18n

See merge request 2-6/2-6-4/terravault/ordinis!187
2026-05-14 13:52:12 +00:00
Александр Зимин 4c29f4e7cb refactor(approval-ux): eng-review fixes — extract helpers, add tests, register i18n 2026-05-14 13:52:12 +00:00
semantic-release-bot 31ad140a02 chore(release): v2.25.0
## [2.25.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.24.0...v2.25.0) (2026-05-14)

###  Features

* **approval-ux:** inline draft CTA + reviewer diff summary + tightened drawer ([fe7f9cd](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/fe7f9cd01f8f2150ecffdc300e260fedb7f8a1cf))
2026-05-14 13:04:42 +00:00
Александр Зимин 139f7d4d30 Merge branch 'feat/approval-ux-editor-cta-and-drawer-diff' into 'main'
feat(approval-ux): inline draft CTA + reviewer diff summary + tightened drawer

See merge request 2-6/2-6-4/terravault/ordinis!186
2026-05-14 12:57:57 +00:00
Andrei Zimin fe7f9cd01f feat(approval-ux): inline draft CTA + reviewer diff summary + tightened drawer
Acts on the two "build now" items from the design review of the approval
workflow UX (other five went to TODOS.md). Plus the TODOS.md file itself,
authored during the same review.

1. **Inline "Создать черновик с моими изменениями" CTA**
   (DictionaryEditorDialog + CreateSchemaDraftModal)

   Was: when a maker edited an approval-required dict, Save disabled and a
   warning told them to "close the editor and click 'Создать черновик схемы'
   on the dict page." Three friction steps and a hunt for a button.

   Now: the warning Alert carries an action button — "Создать черновик с
   моими изменениями" — that opens CreateSchemaDraftModal in-place with the
   maker's in-progress schemaJson pre-loaded. They add a reason and submit.
   No retyping, no hunt.

   Implementation:
   - CreateSchemaDraftModal accepts optional `initialProposedSchema` prop.
     Seed order: edit-mode draft → caller pre-fill → live HEAD.
   - DictionaryEditorDialog mounts the modal inline and triggers it from the
     Alert action. Closes the editor on successful create.

2. **Diff summary chips in ReviewDrawer**

   Was: two raw JSON dumps side by side. Reviewer had to eyeball-diff long
   records to find the actual edit.

   Now: a row of summary chips above the panes — "+N added, −M removed,
   ~K changed" with the field names inline. Computed shallow client-side
   (shallowDiffSummary helper) — ordinis records are flat-ish at the top
   level, no need for a backend diff endpoint. Skipped for CLOSE op (no
   proposed) and when both sides are null.

3. **Tightened drawer header + trimmed empty-state copy**

   Was: single flex-wrap line with four spans (badge + bk + maker + ts) —
   visually busy. Plus a verbose empty-state description: "Когда maker
   отправит schema draft на ревью, он появится здесь."

   Now: two-row layout (identity row on top, provenance row below) so the
   eye lands on Badge + BK first. Empty-state copy shortened to "Очередь
   пуста" / "Схемы на ревью появятся здесь."

Other five gaps (Мои tab, full state-coverage pass, DESIGN.md, a11y audit,
maker notifications) recorded in TODOS.md.
2026-05-14 15:56:50 +03:00
semantic-release-bot bdae52ff28 chore(release): v2.24.0
## [2.24.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.23.1...v2.24.0) (2026-05-14)

###  Features

* **drafts:** audit + outbox для record-draft lifecycle (audit findings) ([0003fb6](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/0003fb68019a39a515f5046df3f039dc3a48f79c))

### 🐛 Fixes

* **approval:** allow non-breaking schema changes inline ([d338c52](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/d338c52c63876d68fabdd5133d6b2e834829a9f9))
* **approval:** close 2 more bypass paths from security audit ([4e09027](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/4e0902706e73e3860eab2618676389aca230e64c))
* **ui:** DictionaryEditorDialog disables Save when draft workflow needed ([898cb34](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/898cb345ec462f2b322a96b3cf5cbc830e4cc079))
2026-05-14 12:52:02 +00:00
Александр Зимин 1b5cea3778 Merge branch 'fix/approval-allow-non-breaking' into 'main'
fix(approval): allow non-breaking schema changes inline

See merge request 2-6/2-6-4/terravault/ordinis!185
2026-05-14 12:35:39 +00:00
Александр Зимин d338c52c63 fix(approval): allow non-breaking schema changes inline 2026-05-14 12:35:39 +00:00
Александр Зимин fe136c9b79 Merge branch 'fix/schema-editor-approval-aware' into 'main'
fix(ui): DictionaryEditorDialog disables Save when draft workflow needed

See merge request 2-6/2-6-4/terravault/ordinis!183
2026-05-14 12:33:43 +00:00
Александр Зимин 898cb345ec fix(ui): DictionaryEditorDialog disables Save when draft workflow needed 2026-05-14 12:33:43 +00:00
Александр Зимин 9ec723dd17 Merge branch 'feat/record-draft-audit-outbox' into 'main'
feat(drafts): audit + outbox для record-draft lifecycle (audit findings)

See merge request 2-6/2-6-4/terravault/ordinis!184
2026-05-14 12:32:06 +00:00
Александр Зимин 0003fb6801 feat(drafts): audit + outbox для record-draft lifecycle (audit findings) 2026-05-14 12:32:06 +00:00
Александр Зимин a7bda82724 Merge branch 'fix/approval-cascade-and-minrole' into 'main'
fix(approval): close 2 more bypass paths from security audit

See merge request 2-6/2-6-4/terravault/ordinis!182
2026-05-14 12:32:03 +00:00
Александр Зимин 4e0902706e fix(approval): close 2 more bypass paths from security audit 2026-05-14 12:32:03 +00:00
semantic-release-bot ce3b495561 chore(release): v2.23.1
## [2.23.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.23.0...v2.23.1) (2026-05-14)

### 🐛 Fixes

* **schema:** enforce approvalRequired on PUT /{name} + PATCH /{name}/schema ([018ebff](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/018ebff2072952828f6b5e7dbd6b19f204e0432a))
2026-05-14 12:15:02 +00:00
Александр Зимин 27c03c3e58 Merge branch 'fix/schema-edit-approval-gate' into 'main'
fix(schema): enforce approvalRequired on PUT/PATCH schema endpoints

See merge request 2-6/2-6-4/terravault/ordinis!181
2026-05-14 12:07:24 +00:00
Andrei Zimin 018ebff207 fix(schema): enforce approvalRequired on PUT /{name} + PATCH /{name}/schema
Reported 2026-05-14: editing schema on an approvalRequired dictionary
applied inline without going through the schema-draft maker-checker
workflow. Two endpoints both lacked the gate that DictionaryRecordService
already had for record CRUD:

1. PUT /api/v1/admin/dictionaries/{name}
   (frontend SchemaDrivenForm "edit schema" save button hits this).
   DictionaryDefinitionService.updateSchema overwrote schemaJson directly.
   Bonus backdoor: same request could simultaneously flip
   approvalRequired:true→false and rewrite the schema in one transaction
   — review-bypass via toggle.

2. PATCH /api/v1/admin/dictionaries/{name}/schema (inline non-breaking
   patch — description / title / minimum / maximum / enum-add). Frontend
   doesn't currently call this, but backend exposed it without a gate.

Both now reject with `422 approval_required` carrying the schema-drafts
URL in the message. Frontend's existing serverErrorMessage in
DictionaryEditorDialog already surfaces backend `message` to the user,
so no UI changes needed for correctness. UX polish (hide "Save" /
show "Create draft" CTA when approvalRequired=true) is a follow-up.

The PUT gate is narrow on purpose: schemaChanged OR approvalRequired
toggle-off. Pure metadata edits (display name, description, locales,
projection flag) on an approvalRequired dict still go through inline
— those don't affect record validation, no review needed.
2026-05-14 15:05:09 +03:00
semantic-release-bot 7202265da1 chore(release): v2.23.0
## [2.23.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.22.1...v2.23.0) (2026-05-14)

###  Features

* **user-display:** KeycloakAdminUserResolver — Phase 2 on-demand lookup ([83caf9c](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/83caf9c3c80e947dc3ad4ff46a194903192ca1f3))
* **user-display:** persistent DB cache + Keycloak resolver hook (Phase 1+2 wiring) ([ec0c74a](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/ec0c74afdf627eab43310c987f009a7a3a1a89d4))

### 🐛 Fixes

* **ui:** UserCell в changelog/events/history — ещё 6 мест ([455ca2f](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/455ca2ff264f4955b5c5b1259c11ce4c3fdd48ce))
2026-05-14 12:00:15 +00:00
Александр Зимин a73549d38d Merge branch 'feat/user-display-persistent-cache' into 'main'
feat(user-display): persistent DB cache + Keycloak Admin lookup (Phase 1+2)

See merge request 2-6/2-6-4/terravault/ordinis!180
2026-05-14 11:52:20 +00:00
Andrei Zimin 83caf9c3c8 feat(user-display): KeycloakAdminUserResolver — Phase 2 on-demand lookup
Implements the Phase 2 hook from the previous commit. With this in
place, UserDisplayService.find chains:

  hot cache → DB (user_display_cache) → Keycloak Admin API

so any realm user resolves on first display, even if they never made
an authenticated request to ordinis. The resolved entry is persisted
via UserDisplayService.upsert with source=KEYCLOAK_ON_DEMAND, so the
next render of the same sub hits the DB tier (~ms) instead of going
back to Keycloak.

Implementation notes:

- Spring RestClient (modern blocking HTTP, replaces RestTemplate).
- client_credentials grant against
  {issuer}/realms/{realm}/protocol/openid-connect/token. Token cached
  in-memory minus a 30s safety margin from `expires_in`.
- 401 on user lookup wipes the cached token and surfaces a
  RuntimeException, so the next resolve refetches.
- 404 on user lookup → Optional.empty (definitive miss, sub not in
  realm). UserDisplayService logs and the caller falls back to short
  UUID. Negative cache TTL not implemented — added complexity not
  justified for the current realm size (~50 users).
- Bean activated only when ordinis.keycloak.admin.enabled=true AND
  the env vars are set. Default disabled — UserDisplayService treats
  KeycloakUserResolver as @Autowired(required = false), so a
  deployment without Keycloak admin creds keeps the previous behavior
  (DB cache only) instead of crashing on startup.

Application config:
- ORDINIS_KEYCLOAK_ADMIN_ENABLED      (false by default)
- ORDINIS_KEYCLOAK_ADMIN_URL          e.g. https://auth.nstart.space
- ORDINIS_KEYCLOAK_ADMIN_REALM        defaults to nstart
- ORDINIS_KEYCLOAK_ADMIN_CLIENT_ID    via vault (see docs-internal/keycloak-admin-setup.md)
- ORDINIS_KEYCLOAK_ADMIN_CLIENT_SECRET via vault

Setup runbook (docs-internal/keycloak-admin-setup.md) covers:
- creating the Keycloak service-account client + assigning view-users
- writing the secret into both vault instances (different per env)
- wiring vault.hashicorp.com agent-inject annotations into the chart
- verification steps + common failure modes

Phase 3 (scheduled bulk sync) is documented at the end of the runbook
but deferred — depends on observed cache miss rate after this lands.
2026-05-14 14:47:49 +03:00
Andrei Zimin ec0c74afdf feat(user-display): persistent DB cache + Keycloak resolver hook (Phase 1+2 wiring)
Closes "ток мой UUID отображается" pain reported on staging today: any
reviewer / maker / publisher / actor whose JWT sub never landed in the
JVM cache shows up as a short UUID in audit / reviews / changelog /
events / history / record drawer / webhook detail / record version
history. Restart the pod and even captured users disappear.

Three-tier resolve, replacing the in-memory-only cache that was the
"Альтернатива (на будущее)" TODO in the original UserDisplayService:

  1. JVM ConcurrentHashMap hot cache (~µs, capped at 10k).
  2. user_display_cache Postgres table (~ms, persistent across restart).
     New migration 0023 — sub PK + preferred_username + name + email +
     source enum + synced_at + updated_at, plus an index on synced_at
     for the scheduled bulk sync that lands later.
  3. Keycloak Admin API on-demand (Phase 2) — dispatched to optional
     KeycloakUserResolver bean. When the bean isn't wired (no Keycloak
     admin creds yet), the third tier is a no-op and UserCell falls
     back to short UUID exactly like before.

Source enum on every row — JWT_CAPTURE / KEYCLOAK_SYNC /
KEYCLOAK_ON_DEMAND — so the eventual scheduled sync can prefer JWT-
captured rows (richest claims as the user actually saw them) and the
on-demand fallback can be distinguished from bulk sync in audits.

JwtUserCaptureFilter and UserDisplayController are unchanged — they
already used UserDisplayService.put / find with the same signatures.
The behavior change is invisible at the API layer: same /admin/users/
{sub}/display endpoint, same 404 user_not_cached on miss; persistence
just survives pod restart now.

mergeFrom on UserDisplayCacheEntry deliberately keeps the existing
non-blank field when an update brings null — Keycloak sync may have a
richer email than JWT capture; don't blank it out.

Phase 2 will land a KeycloakAdminUserResolver impl + vault secret
plumbing on this same branch. Phase 3 (scheduled bulk sync via
@Scheduled) is a separate sprint — it needs the Keycloak admin client
already in place.
2026-05-14 14:45:14 +03:00
Andrei Zimin 455ca2ff26 fix(ui): UserCell в changelog/events/history — ещё 6 мест
После !178 (record drawer + RecordHistoryDrawer + webhook detail) ещё
осталось 6 точек где раньше рендерился UUID. Все они в "истории
словаря" и tab "События":

1. ChangelogDiffModal:57 — header "автор: <name>" в diff modal.
   Было: `{data.publishedBy.name}` (тип ChangelogPublisher.name —
   docstring буквально говорит "Backend пока эхает sub").
   Стало: <UserCell uuid={data.publishedBy.sub} />.

2. TimeTravelModal:686 — список изменений, имя автора рядом с датой.
3. TimeTravelModal:898 — RIGHT panel "История этой версии", dt/dd
   pair с автором.
4. TimeTravelModal ComparePanel:414 — "· {author}" suffix,
   author там DictionaryDetail.updatedBy (тоже UUID).

5. dictionaries.$name.tsx:2263 (events tab, EventsTabContent row) —
   `{r.userId ?? 'anonymous'}` raw. Сменил на UserCell для не-null
   userId, anonymous-fallback оставил без UserCell (нечего lookup'ать).

6. dictionaries.$name.tsx:2399 (history tab, HistoryTabContent entry)
   — `{entry.publishedBy.name}` raw.

Всё через тот же useUserDisplay hook что и в !177 — backend
endpoint /admin/users/{sub}/display + JwtUserCaptureFilter cache.
Если sub нет в cache, UserCell fallback'ит на shortened UUID
(текущее поведение из !177).

ChangelogPublisher type comment в src/api/client.ts уже намекал что
.name это placeholder — useUserDisplay теперь реально резолвит.
2026-05-14 14:33:20 +03:00
semantic-release-bot b5920e4d5f chore(release): v2.22.1
## [2.22.1](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.22.0...v2.22.1) (2026-05-14)

### 🐛 Fixes

* **ui:** wrap remaining UUIDs into UserCell — 3 missed spots ([93b2676](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/93b267699435d36c3bac9c465f400b60d6fcaa65))
2026-05-14 11:13:36 +00:00
Александр Зимин 1b1a9deb9f Merge branch 'fix/user-display-missed-spots' into 'main'
fix(ui): wrap remaining UUIDs into UserCell — 3 missed spots

See merge request 2-6/2-6-4/terravault/ordinis!178
2026-05-14 11:08:33 +00:00
Andrei Zimin 93b2676994 fix(ui): wrap remaining UUIDs into UserCell — 3 missed spots
MR !177 added /admin/users/{sub}/display + UserCell + useUserDisplay,
but only some renderers were migrated. Three places still rendered
raw UUID strings:

1. reviews.tsx:466 — record draft drawer ("Согласование draft" header)
   showed `{draft.makerId}` raw. Tables on the same page already use
   <UserCell uuid={d.makerId} />. Verified via prod staging:
   soloviev.da approved a record draft today and the drawer header
   showed the maker as "77ec2cc8-98e3-4d70-8037-94038fcbde67" instead
   of the username.
2. RecordHistoryDrawer.tsx:110 — version history `updatedBy` raw.
3. webhooks.$id.tsx:235 — webhook subscription `createdBy` raw.

All three switched to <UserCell uuid={...} />, matching the existing
pattern. Added the import where missing. Wrapped each in
inline-flex so the UserCell sits next to the label cleanly.

No backend / API changes — same /admin/users/{sub}/display endpoint
populated by JwtUserCaptureFilter (MR !177).
2026-05-14 14:07:02 +03:00
semantic-release-bot 969395e00d chore(release): v2.22.0
## [2.22.0](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/compare/v2.21.0...v2.22.0) (2026-05-14)

###  Features

* **admin:** scope-gated audit и outbox endpoints ([da17930](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/da17930def89b2fea51be1b8e45b4e5fabe752d1))
* **approval:** enforce per-dictionary approvalMinRole (Phase 2) ([5187845](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/5187845047ba20a6306f5dce8a65f1d4889811fa))
* **records:** close / bulk-close через draft когда approvalRequired ([d66db60](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/d66db60b8496a218501ebade77ff68cc232849d4))
* **users:** /admin/users/{sub}/display endpoint + UserCell uses it ([be90077](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/be90077520607998078a3df5bb5fbe24f1a1bf6e))

### 🐛 Fixes

* **reviews:** friendly error в ReviewDrawer вместо AxiosError ([9436068](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/94360681b6d6412d9d0ae4c5dd4b69600274a034))

### 📝 Docs

* **rbac:** обновить RBAC sections после Phase 1d + Phase 2 ([c41e345](https://git.nstart.cloud/2-6/2-6-4/terravault/ordinis/commit/c41e34545b7a23e24c24196c06a7889724f63338))
2026-05-14 10:37:30 +00:00
Александр Зимин 95c2b46dd3 Merge branch 'feat/user-display-endpoint' into 'main'
feat(users): /admin/users/{sub}/display endpoint + UserCell uses it

See merge request 2-6/2-6-4/terravault/ordinis!177
2026-05-13 16:42:46 +00:00
Александр Зимин be90077520 feat(users): /admin/users/{sub}/display endpoint + UserCell uses it 2026-05-13 16:42:46 +00:00
Александр Зимин 0a9deb51bd Merge branch 'feat/admin-role-gate-audit-outbox-webhooks' into 'main'
feat(admin): scope-gated audit и outbox endpoints

See merge request 2-6/2-6-4/terravault/ordinis!176
2026-05-13 16:42:12 +00:00
Александр Зимин da17930def feat(admin): scope-gated audit и outbox endpoints 2026-05-13 16:42:11 +00:00
Александр Зимин c8d90930e3 Merge branch 'feat/phase2-approval-min-role-enforcement' into 'main'
feat(approval): enforce per-dictionary approvalMinRole (Phase 2)

See merge request 2-6/2-6-4/terravault/ordinis!172
2026-05-13 16:42:09 +00:00
Александр Зимин 5187845047 feat(approval): enforce per-dictionary approvalMinRole (Phase 2) 2026-05-13 16:42:09 +00:00
Александр Зимин 6188062c34 Merge branch 'feat/close-via-draft-when-approval-required' into 'main'
feat(records): close / bulk-close через draft когда approvalRequired

See merge request 2-6/2-6-4/terravault/ordinis!175
2026-05-13 16:41:09 +00:00
Александр Зимин d66db60b84 feat(records): close / bulk-close через draft когда approvalRequired 2026-05-13 16:41:09 +00:00