5 ошибок TS, накопленных за прошлые итерации — теперь pnpm tsc зелёный:
- SchemaDrivenForm: убран unused import formatIsoDateTime + unused
prop `path` (передавался в FieldRenderer, но FieldRendererProps его
не объявлял и FieldBody не использовал)
- dictionaries.$name: удалена неиспользуемая функция toIsoDate
- api/client.ts: добавлен `$schema?: string` в JsonSchema type
(используется в buildSchemaJson и тестируется в types.test.ts)
Backend:
- DictionaryRecordRepository.countActiveGroupedByDictionary — один GROUP BY
по всем справочникам с фильтром по scope, без N+1.
- DictionaryResponse.recordCount (nullable) + factory from(d, count).
- DictionaryDefinitionController передаёт счётчики в list/get,
фильтрованные по currentScopes() пользователя.
Frontend:
- SearchInput над сеткой карточек, client-side filter по
name/displayName/description (case-insensitive, useDeferredValue).
- Badge "N записей" (i18n plural ru/en) в углу карточки.
- "Показано N из M" рядом с поиском.
- EmptyState когда поиск пустой.
До этого audit_log entity была определена, но никто туда не писал — реальный
аудит шёл только через Hibernate Envers (без user/IP/trace). Теперь:
- AuditLogger service пишет в той же транзакции что и CRUD (DictionaryRecordService).
Захватывает: user (JWT sub либо preferred_username), scope, IP (X-Forwarded-For),
UA, trace_id (MDC), request_id. Не ломает основной flow при сбое — только
громко логирует.
- AuditLogRepository: гибкий search() с nullable фильтрами (dictionary, user,
action, businessKey, from, to) + Pageable.
- AuditAdminController: GET /admin/audit (paginated) + /admin/audit/export.csv
(cap 10k строк против OOM).
Frontend:
- /audit route: фильтр-панель, таблица с цветными бейджами (CREATE/UPDATE/CLOSE),
expand-row с JSON before/after diff, footer IP/UA/req_id, кнопка экспорта CSV.
Pagination 50/100/200.
- /outbox route: stat-cards pending/DLQ + DLQ-таблица с last_error.
- Nav links + i18n (RU + EN).