Что нового
8.2.0
Минорный выпусксентябрь 2026

Q.Palette 8.2.0

Продукт держит свои файлы у себя — картинки, переводы, редакторы — и адресует их одним правилом; рутовое приложение перестаёт возить чужое. Режим oidc продлевает и завершает сессию правильно, мигратор 7 → 8 делает больше сам, а базовый образ стал distroless.

  • АссетыПуть без assets/ ведёт в свою сборку — у баннера, карточки, редакторов, переводов.
  • Сессияoidc живёт, пока жив ключ обновления; KeyCloak: микрофронтенды не выбивают друг друга.
  • Рутовое приложениеБез Monaco и демо-данных; панель плагина шапки настраивается.
  • МиграторВкладки и аккордеоны PrimeNG, библиотеки, запуск вне контура.
  • ОбразDistroless без shell и пакетного менеджера; конфигурация — в отдельном каталоге.
  • БезопасностьЗакрыты уязвимости в семи зависимостях, включая critical в undici.
  • АгентыСтандарты UX в паттернах, навык настройки qauth.
  • ИсправленияВосемь ошибок: сессия в oidc и KeyCloak, повреждённые данные в хранилище, режим одной страницы, редактор текста, мигратор.

Куда двигали продукт

Выпуск сложился из шести направлений. Под каждым — работы, из которых оно получилось; подробности живут в статьях документации.

  • Продукт возит своё

    Файл из ассетов продукта находится с любого маршрута одним и тем же путём — и продукт не зависит от того, что лежит в рутовом.

    • Одно правило адресов — QAssetsService: путь без assets/ ведёт в собственную сборку; по нему работают q-banner, q-product-card, qp-plate, q-file-viewer, Monaco и переводы withTransloco
    • Файлы Monaco из рутового убраны — демо-портал уже возит свою копию и задаёт baseUrl явно, это живой пример перехода; гарнитуры тем и бандл редактора текста уедут не раньше 8.3, стандартные картинки переедут в палитру
    • Глобальные стили в сборке UI-сервиса не нужны: уберите styles.scss с импортами палитры — образ станет легче на мегабайты CSS и шрифтов, которые и так отдаёт рутовое
  • Сессия в oidc

    Пользователь, вернувшийся через день, продолжает работу, а нажавший «Выйти» — попадает туда, куда ждал.

    • Сессия в oidc живёт, пока жив ключ обновления: истёкший ключ продлевается при запуске (enableTokenRefresh), действующий — заранее (refreshTokenPeriodically), обновление по 401 сохраняется и не зависает
    • Выход из oidc ведёт на стартовый экран, а не на страницу ошибки провайдера
    • В KeyCloak несколько открытых микрофронтендов больше не выбивают друг друга на форму входа при старте
  • Переход на 8

    Миграция 7 → 8 требует меньше рук и идёт там, где живёт проект.

    • Вкладки и аккордеоны PrimeNG, pTextarea, severity, внутренние импорты — автоматически
    • Проекты-библиотеки распознаются и мигрируют, primeflex убирается, если продукт его не подключает
    • Запуск вне контура и без вопросов: --registry, --skip-steps, без Jenkinsfile, без интерактивных вопросов о коммитах
  • Поставка

    Образ меньше и без лишних поверхностей атаки, известные уязвимости закрыты.

    • Базовый образ PBC UI на distroless: без shell и пакетного менеджера — доустановки и скрипты при старте больше не сработают
    • Конфигурация применяется в отдельном каталоге assets/data/config, если он смонтирован, — стандартные файлы образа не трогаются
    • Из образа рутового ушли демонстрационные данные и Monaco
    • Закрыты уязвимости в browserslist, fast-uri, js-yaml, undici, immutable, shell-quote, svgo — идентификаторы в чейнжлоге
  • Работа над ошибками

    Восемь ошибок, о которых сообщали продукты; условия воспроизведения — в чейнжлоге.

    • Сессия в oidc рвалась при живом ключе обновления: истёкший ключ уводил на вход, обновлённый по 401 не сохранялся, запрос обновления после сна машины висел
    • Выход из oidc приводил на страницу ошибки провайдера
    • В KeyCloak несколько открытых микрофронтендов выбивали друг друга на форму входа
    • Повреждённое значение в localStorage под ключом библиотеки авторизации мешало запуску
    • saveState(undefined) в хранилищах core записывал строку "undefined", чтение падало
    • Режим одной страницы падал при первом входе без раздела visual в настройках
    • Редактор текста qp-plate без входа url оставлял пустой контейнер
    • Мигратор 7 → 8 падал на каталоге с «файловым» именем (input-mask-field.ts/)
  • Документация и агенты

    Ответ есть на странице, а агент в продукте знает стандарты той же версии, что и вы.

Рецепты

Пять задач, которые в этом выпуске решаются короче, чем раньше.

Подключить Monaco из своих ассетов

Копия редактора — в assets/monaco-editor вашей сборки (запись в angular.json), а обёртке достаточно имени каталога:

{ "glob": "**/*", "input": "node_modules/monaco-editor", "output": "assets/monaco-editor" }
MonacoEditorModule.forRoot({ baseUrl: 'monaco-editor' })   // → /api/<сервис>/<компонент>/assets/monaco-editor/min/vs

Копия — полная, без вырезанных языков и воркеров: Monaco на странице один, и её получают все продукты. На прежней версии обёртки — baseUrl: '/api/<сервис>/<компонент>/assets'.

Подробнее — Откуда берётся редактор.

Взять файл из своих ассетов

Путь без ведущего assets/ ведёт в ассеты вашей сборки — с любого маршрута и в любом слоте. Для веб-компонента myproduct/catalog это /api/myproduct/catalog/assets/…. Один сервис для своих запросов:

private readonly assets = inject(QAssetsService);
 
// → /api/myproduct/catalog/assets/data/reference.json
readonly referenceUrl = this.assets.url('data/reference.json');

То же правило у компонентов, принимающих путь к файлу:

<!-- картинка → /api/myproduct/catalog/assets/banner-pics/my-banner.jpg -->
<q-banner picture="banner-pics/my-banner.jpg"></q-banner>
 
<!-- бандл редактора → /api/myproduct/catalog/assets/qpalette-plate-wc/main.js -->
<qp-plate [value]="editorValue" url="qpalette-plate-wc"></qp-plate>

Файлы лежат в src/assets/ вашего проекта — banner-pics/my-banner.jpg и скопированный пакет @diasoft/qpalette-plate-wc; путь assets/… или от корня, как раньше, ведёт в рутовое. В свои ассеты кладите только картинки, которые должны отличаться от стандартных, — стандартные остаются доступны и позже переедут в палитру.

Подробнее — Адреса собственных ассетов.

Переводы без имени пакета в адресе

provideQLocalization(
  withTransloco({ translationsUrl: 'i18n' })
)

Подробнее — Адрес переводов.

Не терять сессию в oidc

Продление при запуске и заранее — двумя настройками; провайдер должен выдавать ключ обновления (у qauth — scope offline_access):

{
  "auth": {
    "service": "oidc",
    "options": {
      "enableTokenRefresh": true,
      "refreshTokenPeriodically": true,
      "userManagerSettings": {
        "scope": "openid profile email roles offline_access"
      }
    }
  }
}

Подробнее — Продление сессии по ключу обновления.

Панель плагина на всю высоту экрана

Кнопка с фоном и панель, растянутая от кнопки до нижнего края, — без подсчёта высоты шапки:

{
  "endpoint": { "service": "qdemo", "component": "qdemo", "route": "plugins/assistant" },
  "slot": "header",
  "icon": { "name": "pi-comments-outlined", "color": "#ffffff", "background": "var(--q-primary)" },
  "caption": "Ассистент",
  "panel": { "width": "24rem", "bottom": "1rem" }
}

Подробнее — Размеры панели.

Breaking changes

  • Monaco — файлов редактора в рутовом больше нет: возите копию monaco-editor в своих ассетах и задайте baseUrl (рецепт)
  • @diasoft/qpalette-openspec не выпускается — вместо qpalette openspec sync в скриптах qpalette skills sync
  • Базовый образ PBC UI — distroless: без пакетного менеджера и shell — доустановка пакетов и скрипты при старте в образах-наследниках перестанут работать

Подробнее — раздел «Требует действий» в чейнжлоге.

Что не попало в этот обзор

Здесь — то, ради чего выпуск делался. Список закрытых уязвимостей с идентификаторами и что убрано из рутового приложения — в чейнжлоге 8.2.0.