Перейти к содержанию

Ролевая модель

Модуль CM Ocean Loyalty работает как OAuth2 resource server: бэкенд loyalty-billing проверяет JWT, выпущенный Keycloak, не хранит сессий (stateless) и придерживается принципа deny-by-default — любой вызов API требует аутентификации, а на каждой операции навешана проверка прав @PreAuthorize. Доступ к функции есть только тогда, когда у пользователя (или сервисного клиента) явно присутствует соответствующая роль.

Откуда берутся роли

Роли приходят в JWT в клейме resource_access[<client>].roles и имеют продуктовый префикс LOYALTY_. Имя роли построено по шаблону LOYALTY_<ДОМЕН>_<ДЕЙСТВИЕ>, где действие — это READ (чтение) либо WRITE (изменение); для части функций действие разбито тоньше: право на справочник тегов и отдельное право на присвоение тега клиенту, право правки акции и отдельные права на её согласование (APPROVE) и запуск (ACTIVATE), право правки конфигурации программы и отдельное право на её активацию, отдельные права на активацию и удаление версий настройки карточки клиента (ACTIVATE, DELETE), отдельное право на приём сегментов (INTAKE). Назначение и выдача ролей выполняются на стороне Keycloak — client-роли на общем клиенте входа frontend (том же, что у Core UI и модуля Promo); модуль их только проверяет.

Типы клиентов

Интерактивный (UI) клиент использует authorization code flow — через него работают операторы из единого окна Core UI. Сервисные и интеграционные потребители (POS, RT Flow, Check Scan, модуль Promo, Batch Flow и т. п.) используют client credentials. Набор проверяемых ролей для обоих типов клиентов одинаков — различается лишь способ получения токена.

Клиентский кабинет (B2C) — отдельный контур

Мобильный кабинет участника (/v1/b2c/**) защищён не ролями LOYALTY_*, а отдельным scope loyalty.b2c клиентского токена (см. «B2C-кабинет»). Единственное пересечение с ролевой моделью — staff-предпросмотр: сотрудник с ролью LOYALTY_PROFILE_READ может открыть кабинет без клиентского токена, для поддержки. Участник выбирается параметром запроса previewExternalId; без параметра открывается участник, заданный настройкой loyalty.b2c.preview-external-id (см. Конфигурация). Просмотр с явно переданным previewExternalId попадает в журнал аудита как обращение к персональным данным участника. Клиентская ветка параметр не читает.

Реестр сотрудников

Бэкенд запоминает сотрудников по их токенам — идентификатор, имя, логин, e-mail и роли LOYALTY_* — без обращения к Keycloak Admin API. В реестр попадают только люди с ролями продукта, входившие хотя бы раз; клиентские токены и сервисные учётки интеграций (service-account-*) в него не попадают. Реестр — источник списка согласующих при отправке акции на согласование (GET /v1/users) и подписей «ФИО (логин)» у автора и активировавшего конфигурацию программы; e-mail наружу не отдаётся. Пока сотрудник ни разу не вошёл после выдачи роли, в списках его нет.

Публичные эндпоинты

Без аутентификации доступны только следующие эндпоинты:

Назначение Путь Порт
Проверки здоровья (k8s liveness/readiness) GET /health/** management, 9090
Метрики Prometheus /metrics management, 9090
Информация о сборке /info management, 9090
Спецификация OpenAPI / Swagger UI /v3/api-docs/**, /swagger-ui/** прикладной, 8080

Вся бизнес-функциональность API (/v1/...) закрыта и требует роли из таблиц ниже. Исключение — часовой пояс программы GET /v1/program/timezone: он доступен любому аутентифицированному сотруднику без роли продукта, потому что по нему интерфейс показывает все даты.

Полный перечень ролей

Ниже — весь состав ролей LOYALTY_*, объявленных в реестре ролей бэкенда и заведённых как клиентские роли на клиенте frontend в Keycloak, сгруппированный по предметной области. Столбец «Кому выдаётся» — ориентир, а не жёсткое предписание: конкретный набор ролей у пользователя определяет администратор Keycloak.

Клиенты, профиль, теги

Роль Что открывает Кому выдаётся
LOYALTY_CUSTOMER_READ Каталог клиентов, карточка клиента, схема и структура карточки клиента, справочники полей профиля, строки таблиц данных по клиенту Оператор
LOYALTY_CUSTOMER_WRITE Создание клиента, правка профиля (запись в MDM), блокировка/разблокировка, архивирование/разархивирование, мягкое удаление, слияние «1 телефон = 1 профиль», массовые операции каталога, импорт клиентов, обезличивание (наравне с LOYALTY_INTEGRATION_WRITE) Оператор
LOYALTY_PROFILE_READ Сводный профиль клиента (идентификация MDM + данные лояльности), бейджи клиента; также даёт staff-доступ к B2C-кабинету участника для поддержки Оператор
LOYALTY_ACCOUNT_READ Счета клиента и баланс баллов (доступно / в резерве) Оператор
LOYALTY_ACCOUNT_WRITE Создание счёта клиента Оператор
LOYALTY_TAG_READ Справочник тегов клиента — просмотр, выбор тегов в фильтре каталога и в условиях аудитории акций Оператор, маркетолог
LOYALTY_TAG_WRITE Справочник тегов — создание, переименование, слияние, удаление, перенос; заведение недостающих тегов при создании клиента по API и импортом Администратор НСИ
LOYALTY_CUSTOMER_TAG_WRITE Присвоение и снятие тегов клиенту (отдельно от справочника и от LOYALTY_CUSTOMER_WRITE) — в каталоге клиентов и операциями «Добавить теги» / «Снять теги» экрана «Ручные операции» Оператор
LOYALTY_CLIENT_PROFILE_ACTIVATE Активация версии настройки карточки клиента. Правка черновика настройки остаётся под LOYALTY_DICTIONARY_WRITE и права на активацию не даёт Администратор НСИ, рецензент настройки
LOYALTY_CLIENT_PROFILE_DELETE Удаление версий настройки карточки клиента (одиночное и пакетное). Ни правка, ни активация этого права не дают: удалённую версию не вернуть Администратор НСИ

Операции с баллами

Роль Что открывает Кому выдаётся
LOYALTY_ACCRUAL_WRITE Начисление баллов — одиночное, массовое и через экран «Ручные операции» (пакет по списку, файлом) Оператор ручных операций
LOYALTY_REDEMPTION_WRITE Списание: резерв (hold), фиксация/отмена резерва, прямое списание, корректировка, ручное сгорание (/expirations) Оператор ручных операций
LOYALTY_TIER_WRITE (в этой роли) Перевод уровня клиента как ручная операция экрана «Ручные операции» Оператор ручных операций
LOYALTY_CUSTOMER_TAG_WRITE (в этой роли) Добавление и снятие тегов по списку клиентов или файлу на экране «Ручные операции» Оператор ручных операций
LOYALTY_OPERATION_REASON_OTHER_WRITE Причина «Прочее» справочника причин операций — поверх права на саму операцию (ACCRUAL_WRITE/REDEMPTION_WRITE/TIER_WRITE) Оператор с расширенным доступом (не выдаётся всем операторам ручных операций)
LOYALTY_OPERATION_WRITE Пополнение, списание, перевод и обмен баллов между счетами леджера (/top-up, /withdraw, /transfer, /exchange) Оператор финансовых операций
LOYALTY_EVENT_WRITE Регистрация покупки (покупка → акция → начисление) Интеграция (касса/POS)
LOYALTY_MAINTENANCE_WRITE Регламентное сгорание просроченных баллов, постановка предупреждений о сгорании в очередь, запуск внутренней сверки итогов (/admin/reconciliation/runs) Эксплуатация

Уровни и конфигурация программы

Роль Что открывает Кому выдаётся
LOYALTY_TIER_READ Уровни (по умолчанию — активной конфигурации программы), параметры уровня (кастомные поля), текущий уровень клиента с прогрессом, журнал переходов Оператор, маркетолог
LOYALTY_TIER_WRITE Параметры уровня — поля и их значения, ручное назначение/снятие уровня клиента (override + причина), массовый перевод уровня. Сам набор уровней правится только в составе конфигурации программы Администратор программы
LOYALTY_PROGRAM_CONFIG_READ Раздел «Конфигурации программы»: каталог, карточка конфигурации, история активаций, список авторов, базовая денежная валюта для мастера Администратор программы, маркетолог
LOYALTY_PROGRAM_CONFIG_WRITE Создание конфигурации, правка черновика, дублирование, удаление (одиночное и пакетное) Администратор программы
LOYALTY_PROGRAM_CONFIG_ACTIVATE Активация конфигурации программы. Право правки его не подразумевает — роли отзываются независимо Администратор программы

Акции, согласование, метки, достижения

Роль Что открывает Кому выдаётся
LOYALTY_PROMOTION_READ Каталог механик, список и карточки акций, статистика, история согласования, реестр условий и справочники формы акции, партнёры и партнёрские предложения (чтение), экспорт акций/механик между контурами Маркетолог
LOYALTY_PROMOTION_WRITE Создание, изменение, приостановка, отмена запуска, архивирование/возврат из архива, удаление, копия, новая версия правила, массовые действия, отправка на согласование и её отмена, выбор согласующих из реестра сотрудников, партнёры и партнёрские предложения (запись), проставление и снятие меток на акции, импорт акций/механик. Запуск акции не открывает Маркетолог
LOYALTY_PROMOTION_ACTIVATE Запуск акции — одиночный и массовый; требуется всегда, независимо от того, включено ли согласование Маркетолог или ответственный за запуск
LOYALTY_PROMOTION_APPROVE Согласование и отклонение запуска акции (принцип «четырёх глаз»); решение по своей же отправке отклоняется Согласующий — не автор акции
LOYALTY_PROMOTION_LABEL_READ Справочник меток акций — просмотр, выбор меток в форме акции и в фильтре каталога Маркетолог
LOYALTY_PROMOTION_LABEL_WRITE Справочник меток — создание, переименование, слияние, удаление, перенос; заведение недостающих меток при создании акции по API Маркетолог (по умолчанию — обе роли на метки)
LOYALTY_ACHIEVEMENT_READ Каталог правил достижений «условие — бейдж» — просмотр Маркетолог
LOYALTY_ACHIEVEMENT_WRITE Каталог достижений — создание, изменение, удаление; пересчёт бейджей клиента Маркетолог

Согласование запуска акции

Согласование включается настройкой развёртывания loyalty.promotion.approval.enabled (env LOYALTY_PROMOTION_APPROVAL_ENABLED, по умолчанию выключено). При выключенном согласовании его действия отвечают 409 approval_disabled, а запуск идёт без согласования — но всё равно только с правом LOYALTY_PROMOTION_ACTIVATE. При включённом запуск несогласованного черновика отклоняется 409 approval_required.

Сегменты клиентов

Роль Что открывает Кому выдаётся
LOYALTY_SEGMENT_READ Экран «Сегменты клиентов»: список сегментов с числом клиентов и действующих акций, журнал заливок Маркетолог, администратор НСИ
LOYALTY_SEGMENT_WRITE Архивация, возврат из архива и удаление сегмента Администратор НСИ
LOYALTY_SEGMENT_INTAKE Приём сегментов из Batch Flow (/v1/integration/customer-segments/**): регистрация сегмента, пачки участников, завершение заливки Только учётная запись Batch Flow

Приём — отдельное право, а не общее интеграционное: заливка меняет, кому начисляют все сегментные акции сразу.

Валюты и курсы

Роль Что открывает Кому выдаётся
LOYALTY_CURRENCY_READ Просмотр справочника валют (GET /v1/currencies) Оператор, маркетолог
LOYALTY_EXCHANGE_RATE_READ Просмотр курсов обмена между валютами баллов Оператор, маркетолог

Ведение справочника валют программы (создание, правка, история курса) и пар обмена валют идёт под LOYALTY_DICTIONARY_READ/LOYALTY_DICTIONARY_WRITE — как и у прочих разделов администрирования, а не под LOYALTY_CURRENCY_*.

Справочники (НСИ) и настройка программы

Роль Что открывает Кому выдаётся
LOYALTY_DICTIONARY_READ Реестр справочников и записи справочников общего реестра, справочник валют программы и пары обмена, субсчета баллов (наравне с правом на ручные операции), операционная конфигурация, лимиты и политика списания, глобальная механика, настройка профиля клиента (поля, группы, таблицы, версии, источники данных), реестр условий акции («Настройка акции»), список городов профиля без определённого часового пояса Администратор НСИ, оператор ручных операций (нужна для чтения справочника причин операций — см. предупреждение ниже)
LOYALTY_DICTIONARY_WRITE Запись перечисленного выше: создание/изменение/удаление записей локальных справочников, субсчета, справочник валют и пары обмена, операционная конфигурация, лимиты и политика списания, глобальная механика, правка настройки профиля клиента (без активации и удаления версий), реестр условий акции Администратор НСИ
LOYALTY_CITY_READ / LOYALTY_CITY_WRITE Справочник городов (/v1/admin/cities): просмотр; создание, правка, архивация Администратор НСИ
LOYALTY_STORE_READ / LOYALTY_STORE_WRITE Справочник торговых точек (/v1/admin/stores): просмотр; создание, правка, закрытие Администратор НСИ
LOYALTY_MERCHANT_READ / LOYALTY_MERCHANT_WRITE Справочник мерчантов (/v1/admin/merchants): просмотр; создание, правка, закрытие Администратор НСИ
LOYALTY_PRODUCT_CATALOG_READ / LOYALTY_PRODUCT_CATALOG_WRITE Каталог товаров — категории (/v1/admin/product-categories) и товары (/v1/admin/product-items): просмотр; создание, правка, архивация, удаление, импорт из CSV Администратор НСИ

Справочники со своим экраном — исключение

Общие LOYALTY_DICTIONARY_READ/LOYALTY_DICTIONARY_WRITE не открывают справочники со своим экраном: теги клиента, метки акций, сегменты клиентов, города, торговые точки, мерчанты, категории товаров и SKU. У каждого своя пара ролей (см. таблицы выше; категории и SKU делят LOYALTY_PRODUCT_CATALOG_*). Строка такого справочника в общем реестре (GET /v1/admin/dictionaries) видна только с его собственной read-ролью; вызов generic-эндпоинтов по его ключу отвечает 409 dictionary_own_screen. Сам реестр читается только с LOYALTY_DICTIONARY_READ: без неё экраны «Теги клиентов», «Метки акций» и «Сегменты клиентов» открываются лишь по прямой ссылке. Подробнее — «Справочники и НСИ».

LOYALTY_DICTIONARY_READ нужна операторам операций с баллами и уровнем

Причины начисления, корректировки и перевода уровня — коды справочника «Причины операций», который формы всех трёх операций читают через GET /v1/admin/dictionaries/{key}/entries. Без LOYALTY_DICTIONARY_READ форма операции сообщает «Справочник причин недоступен — операция невозможна», даже если у оператора есть право на саму операцию. Операциям с тегами причина не нужна.

Мониторинг, бизнес-день, аудит, отчёты

Роль Что открывает Кому выдаётся
LOYALTY_MONITORING_READ Сводки и динамика, аномалии операций, баллы к сгоранию, журнал ручных начислений, история операций клиента, текущий бизнес-день и дневные отчёты, раздел «Отчёты» (/v1/reports/**), сквозной журнал аудита (список, целостность, выгрузка), список и диффы прогонов сверки итогов Мониторинг, аналитик, аудитор, эксплуатация
LOYALTY_BUSINESS_DAY_WRITE Закрытие текущего бизнес-дня Эксплуатация

Собственной read-роли у журнала аудита, у сверки итогов и у отчётов нет — все три читаются той же ролью LOYALTY_MONITORING_READ, что и остальной мониторинг. Вкладки раздела «Отчёты» между собой по ролям не разграничены.

Очередь приёма

Роль Что открывает Кому выдаётся
LOYALTY_INTAKE_READ Экран «Очередь приёма»: список и карточка отложенной команды Администратор, эксплуатация
LOYALTY_INTAKE_WRITE Подача команды в очередь (POST /v1/intake/commands — интеграционная точка входа, не экран); на экране очереди — «Вернуть в работу» и «Отменить» (в т. ч. отменить команду, назначенную на будущее) Интеграция (подача команд), администратор/эксплуатация (разбор очереди)

Исходящие уведомления

Роль Что открывает Кому выдаётся
LOYALTY_NOTIFICATION_READ Сообщения очереди исходящих уведомлений, отложенные в разбор (GET /v1/admin/notifications) Эксплуатация
LOYALTY_NOTIFICATION_WRITE Возврат сообщения в очередь и снятие из разбора с основанием Эксплуатация

Экрана у разбора исходящих уведомлений нет — он выполняется через API.

Обмен данными

Роль Что открывает Кому выдаётся
LOYALTY_EXCHANGE_READ Ленты изменений (клиенты, операции, счета) и журнал прогонов регламентного обмена с внешними системами и DWH Интеграция, DWH
LOYALTY_EXCHANGE_WRITE Управление регламентом обмена: расписание задания, ручной запуск, изменение порогов Интеграция, эксплуатация

LOYALTY_EXCHANGE_READ намеренно отделена от LOYALTY_INTEGRATION_READ: лента изменений отдаёт реестр клиентов целиком, включая персональные данные, а не точечную резолюцию по одному клиенту — поэтому её не раздают тем же клиентам, что несут LOYALTY_INTEGRATION_*.

Интеграции

Роль Что открывает Кому выдаётся
LOYALTY_INTEGRATION_READ Резолюция карты лояльности на POS, обзор клиента для Check Scan, сегменты клиента, проверка условий для RT Flow (read/resolve-контур, без записи) Интеграция (POS, Check Scan, RT Flow)
LOYALTY_INTEGRATION_WRITE Приём чеков POS и возвратов по чеку (с отменой возврата), начислений и сторно от модуля Promo, начислений от RT Flow, транзакций партнёрской программы, внешних итогов для сверки; наравне с LOYALTY_CUSTOMER_WRITE допускается к обезличиванию клиента Интеграция (POS, Promo, RT Flow, партнёрские системы)

Составные правила доступа

Часть операций требует не одной роли, а их сочетания или альтернативы — правило собрано в реестре ролей и проверяется либо на самой ручке (@PreAuthorize), либо в сервисе, когда решение зависит от данных запроса:

Правило Условие Где применяется
Карточка клиента LOYALTY_PROFILE_READ И LOYALTY_MONITORING_READ GET /v1/customers/{externalId}/card, реферальный блок и список рефералов, партии баллов (points-lots), сегменты клиента, история статусов
Ручная операция (любая) LOYALTY_ACCRUAL_WRITE ИЛИ LOYALTY_REDEMPTION_WRITE ИЛИ LOYALTY_TIER_WRITE ИЛИ LOYALTY_CUSTOMER_TAG_WRITE Открытие экрана «Ручные операции», приём и статус пакета, отчёт по пакету, импорт файла; право на конкретную выбранную операцию в пакете проверяется по ней (начисление — ACCRUAL_WRITE, корректировка — REDEMPTION_WRITE, перевод уровня — TIER_WRITE, добавление и снятие тегов — CUSTOMER_TAG_WRITE), а не по факту доступа к ручке
Просмотр субсчетов LOYALTY_DICTIONARY_READ ИЛИ любая из ролей ручной операции GET /v1/points-subaccounts (список нужен и при выборе субсчёта в форме операции)
Список тегов LOYALTY_TAG_READ ИЛИ LOYALTY_CUSTOMER_TAG_WRITE GET /v1/tags, POST /v1/tags/lookup — тому, кто только присваивает теги, тоже нужно из чего выбирать
Список сегментов LOYALTY_SEGMENT_READ ИЛИ LOYALTY_PROMOTION_READ ИЛИ LOYALTY_DICTIONARY_READ ИЛИ LOYALTY_CUSTOMER_READ GET /v1/customer-segments — поле выбора сегмента в акциях, партнёрских предложениях, ограничениях списания и каталоге клиентов
Создание клиента с тегами LOYALTY_CUSTOMER_WRITE, а если запрос несёт tags/tagIds — дополнительно LOYALTY_CUSTOMER_TAG_WRITE POST /v1/customers
Обезличивание ПДн LOYALTY_CUSTOMER_WRITE ИЛИ LOYALTY_INTEGRATION_WRITE POST /v1/customers/{externalId}/anonymize
Действие согласования акции На ручке — LOYALTY_PROMOTION_WRITE ИЛИ LOYALTY_PROMOTION_APPROVE; сервис уточняет: submit/cancel — право записи (иначе 403 access_denied), approve/reject — право согласующего (иначе 403 approval_forbidden) POST /v1/promotions/{id}/approvals/{type}; решение по своей же отправке — 409 approval_self_forbidden, при поимённом списке решают только перечисленные — иначе 403 approval_not_assigned
Сохранение конфигурации с акциями уровней LOYALTY_PROGRAM_CONFIG_WRITE, а если сохранение меняет условия акций (множество акций уровня, снятие с программы акции, стоящей на уровне, удаление уровня с акциями) — дополнительно LOYALTY_PROMOTION_WRITE POST /v1/program-configs, PATCH /v1/program-configs/{id}; дублирование и удаление конфигурации этого права не требуют

Заведение недостающего значения справочника из данных

Создание/импорт клиента с незнакомым тегом заводит его в справочнике только при наличии LOYALTY_TAG_WRITE у вызывающего — иначе 422 unknown_tag. Симметрично для акций: незнакомая метка заводится только при LOYALTY_PROMOTION_LABEL_WRITE, иначе 422 unknown_label. Это не @PreAuthorize, а проверка внутри сервиса по фактическим authorities текущего субъекта.

Соответствие ролей и операций

Привязка «роль → метод и путь» приведена ниже. Префикс API — /v1.

Клиенты, счета, баланс, профиль, теги

Роль Метод и путь
LOYALTY_CUSTOMER_READ GET /v1/customers, GET /v1/customers/{externalId}, GET /v1/client-profile/schema, GET /v1/client-profile/structure, GET /v1/client-profile/dictionaries/{key}, GET /v1/customers/{externalId}/profile-tables/{groupId}/rows
LOYALTY_CUSTOMER_WRITE PUT /v1/customers/{externalId}/profile, POST /v1/customers/{externalId}/block\|unblock\|merge\|archive\|unarchive, DELETE /v1/customers/{externalId}, PUT /v1/customers/{externalId}/attributes, POST /v1/customers/bulk-block\|bulk-unblock\|bulk-archive\|bulk-unarchive\|bulk-delete, POST /v1/customers/import, POST /v1/customers/import/validate
Создание клиента с тегами¹ POST /v1/customers
Обезличивание ПДн¹ POST /v1/customers/{externalId}/anonymize
LOYALTY_ACCOUNT_READ GET /v1/customers/{externalId}/accounts, GET /v1/customers/{externalId}/accounts/{accountNumber}, GET /v1/customers/{externalId}/balance
LOYALTY_ACCOUNT_WRITE POST /v1/customers/{externalId}/accounts
LOYALTY_PROFILE_READ GET /v1/customers/{externalId}/profile, GET /v1/customers/{externalId}/achievements
Карточка клиента¹ GET /v1/customers/{externalId}/card, GET /v1/customers/{externalId}/referral, GET /v1/customers/{externalId}/referrals, GET /v1/customers/{externalId}/points-lots, GET /v1/customers/{externalId}/segments, GET /v1/customers/{externalId}/status-history
LOYALTY_DICTIONARY_READ GET /v1/admin/client-profile/fields, GET /v1/admin/client-profile/groups, GET /v1/admin/client-profile/groups/{id}/columns, GET /v1/admin/client-profile/table-sections, GET /v1/admin/client-profile/source-schemas\|source-tables\|source-columns, GET /v1/admin/client-profile/configurations, GET /v1/admin/client-profile/configurations/{id}, GET .../configurations/{id}/diff
LOYALTY_DICTIONARY_WRITE POST/PUT/DELETE /v1/admin/client-profile/fields* (в том числе order, bulk-delete, {id}/archive, {id}/unarchive), POST/PUT/DELETE /v1/admin/client-profile/groups* (в том числе order, {id}/columns), POST/PUT/DELETE /v1/admin/client-profile/table-sections* (в том числе order), PATCH /v1/admin/client-profile/configurations/{id}, POST .../configurations/{id}/copy
LOYALTY_CLIENT_PROFILE_ACTIVATE POST /v1/admin/client-profile/configurations/{id}/activate
LOYALTY_CLIENT_PROFILE_DELETE DELETE /v1/admin/client-profile/configurations/{id}, POST /v1/admin/client-profile/configurations/bulk-delete
LOYALTY_TAG_READ или LOYALTY_CUSTOMER_TAG_WRITE GET /v1/tags, POST /v1/tags/lookup
LOYALTY_TAG_READ GET /v1/tags/customer-counts, GET /v1/tags/{tagId}/condition-promotions, GET /v1/tags/condition-promotions
LOYALTY_TAG_WRITE POST /v1/tags, PATCH /v1/tags/{tagId}, POST /v1/tags/{tagId}/merge, POST /v1/tags/bulk-delete, GET /v1/tags/export, POST /v1/tags/import
LOYALTY_CUSTOMER_TAG_WRITE POST /v1/customers/bulk-tag-assign, POST /v1/customers/bulk-tag-remove

¹ Составное правило — см. раздел «Составные правила доступа» выше; это не имя роли в Keycloak.

Начисления, списания, ручные операции

Роль Метод и путь
LOYALTY_ACCRUAL_WRITE POST /v1/customers/{externalId}/accruals, POST /v1/customers/bulk-accruals
LOYALTY_REDEMPTION_WRITE POST /v1/customers/{externalId}/holds, POST /v1/customers/{externalId}/holds/{holdId}/commit\|cancel, POST /v1/customers/{externalId}/redemptions, POST /v1/customers/{externalId}/corrections, POST /v1/customers/{externalId}/expirations, POST /v1/customers/bulk-corrections
LOYALTY_TIER_WRITE POST /v1/customers/tier-bulk (в составе ручных операций)
LOYALTY_OPERATION_REASON_OTHER_WRITE Причина OTHER в теле любой из ручных операций выше — проверяется сервисом, не отдельным путём
Право на ручную операцию (любую)¹ POST /v1/customers/operations/batches (приём пакета, в том числе операций с тегами), GET /v1/customers/operations/batches, GET .../batches/{batchId}, GET .../batches/{batchId}/events, GET .../batches/{batchId}/report, POST /v1/customers/operations/import/validate, POST /v1/customers/operations/import/validate/report
LOYALTY_OPERATION_WRITE POST /v1/top-up, POST /v1/withdraw, POST /v1/transfer, POST /v1/exchange
LOYALTY_EVENT_WRITE POST /v1/events/purchase
LOYALTY_MAINTENANCE_WRITE POST /v1/maintenance/points/expire, POST /v1/maintenance/points/expiry-notice, POST /v1/admin/reconciliation/runs

Уровни и конфигурация программы

Роль Метод и путь
LOYALTY_TIER_READ GET /v1/tiers (необязательный configId), GET /v1/customers/{externalId}/tier, GET /v1/customers/{externalId}/tier/transitions, GET /v1/tiers/{code}/attributes, GET /v1/tier-profile/schema, GET /v1/admin/tier-profile/fields
LOYALTY_TIER_WRITE PUT /v1/customers/{externalId}/tier, DELETE /v1/customers/{externalId}/tier, PUT /v1/tiers/{code}/attributes, POST/PUT/DELETE /v1/admin/tier-profile/fields* (в том числе order)
LOYALTY_PROGRAM_CONFIG_READ GET /v1/program-configs, GET /v1/program-configs/{id}, GET /v1/program-configs/activations, GET /v1/program-configs/activations/{activationId}, GET /v1/program-configs/authors, GET /v1/program-configs/base-currency
LOYALTY_PROGRAM_CONFIG_WRITE POST /v1/program-configs, PATCH /v1/program-configs/{id}, DELETE /v1/program-configs/{id}, POST /v1/program-configs/bulk-delete, POST /v1/program-configs/duplicate
LOYALTY_PROGRAM_CONFIG_ACTIVATE POST /v1/program-configs/{id}/activate

Правка и удаление уровня отдельным путём (PUT/DELETE /v1/tiers/{code}) не поддерживаются: набор уровней сохраняется только в составе конфигурации программы.

Акции, согласование, метки, достижения, партнёры

Роль Метод и путь
LOYALTY_PROMOTION_READ GET /v1/mechanics*, GET /v1/promotions* (в том числе stats, authors, criteria, {id}/stats, {id}/approvals, {id}/criteria/attribute-activity, .../participation-limit), GET /v1/promotions/dictionaries/{key}/entries, POST /v1/promotions/dictionaries/{key}/entries/lookup, GET /v1/admin/promotions/export, GET /v1/admin/mechanics/export, GET /v1/partners*, GET /v1/partners/{id}/settlement, GET /v1/partner-offers*
LOYALTY_PROMOTION_WRITE POST/PUT/DELETE /v1/promotions*, действия ЖЦ (unschedule, pause, archive, unarchive, revise, copy) и их bulk-варианты, POST /v1/promotions/bulk-delete, PUT/DELETE .../participation-limit, POST /v1/promotions/bulk-label-assign\|bulk-label-remove, POST /v1/admin/promotions/import, POST /v1/admin/mechanics/import, POST/PUT/DELETE /v1/partners*, POST/PUT/DELETE /v1/partner-offers*, POST /v1/partner-offers/{id}/status, GET /v1/users
LOYALTY_PROMOTION_ACTIVATE POST /v1/promotions/{id}/activate, POST /v1/promotions/bulk-activate
Действие согласования¹ POST /v1/promotions/{id}/approvals/{submit\|approve\|reject\|cancel}
LOYALTY_PROMOTION_LABEL_READ GET /v1/promotion-labels, POST /v1/promotion-labels/lookup, GET .../condition-promotions
LOYALTY_PROMOTION_LABEL_WRITE POST /v1/promotion-labels, PATCH /v1/promotion-labels/{id}, POST /v1/promotion-labels/{id}/merge, POST /v1/promotion-labels/bulk-delete, GET /v1/promotion-labels/export, POST /v1/promotion-labels/import
LOYALTY_ACHIEVEMENT_READ GET /v1/admin/achievements, GET /v1/admin/achievements/{id}
LOYALTY_ACHIEVEMENT_WRITE POST/PUT/DELETE /v1/admin/achievements*, POST /v1/customers/{externalId}/achievements/recheck

Сегменты клиентов

Роль Метод и путь
Список сегментов¹ GET /v1/customer-segments
LOYALTY_SEGMENT_READ GET /v1/admin/customer-segments/fills, GET /v1/admin/customer-segments/fills/segments
LOYALTY_SEGMENT_WRITE POST /v1/customer-segments/{code}/archive\|unarchive, DELETE /v1/customer-segments/{code}
LOYALTY_SEGMENT_INTAKE PUT /v1/integration/customer-segments/{code}, POST .../{code}/fills/{fillId}/members, POST .../{code}/fills/{fillId}/complete

Валюты, курсы, справочники, конфигурация

Роль Метод и путь
LOYALTY_CURRENCY_READ GET /v1/currencies, GET /v1/currencies/{code}
LOYALTY_EXCHANGE_RATE_READ GET /v1/exchange-rates
LOYALTY_DICTIONARY_READ GET /v1/admin/dictionaries*, GET /v1/admin/dictionaries/export, GET /v1/admin/currencies* (в том числе {code}/rates), GET /v1/admin/exchange-pairs* (в том числе summary, base-rate), GET /v1/admin/point-currencies, GET /v1/admin/system-config, GET /v1/admin/redemption-limits, GET /v1/admin/redemption-policy, GET /v1/admin/global-mechanic, GET /v1/admin/promotion-criteria, GET /v1/admin/promotion-criteria/attribute-stats, GET /v1/admin/timezones/unmatched-cities, GET /v1/points-subaccounts/{id}, GET /v1/points-subaccounts/{id}/totals
LOYALTY_DICTIONARY_WRITE POST/DELETE/status /v1/admin/dictionaries/{key}/entries*, POST /v1/admin/dictionaries/import, POST/PUT/DELETE /v1/admin/currencies*, POST/PUT/DELETE /v1/admin/exchange-pairs*, PUT/DELETE /v1/admin/point-currencies/{code}, PUT /v1/admin/system-config/{key}, PUT/DELETE /v1/admin/redemption-limits/{scopeType}/{scopeKey}, PUT /v1/admin/redemption-policy, PUT /v1/admin/global-mechanic, PUT /v1/admin/promotion-criteria, POST /v1/points-subaccounts, PUT /v1/points-subaccounts/{id}, PUT /v1/points-subaccounts/priority, POST /v1/points-subaccounts/{id}/activate\|close
LOYALTY_DICTIONARY_READ или право на ручную операцию¹ GET /v1/points-subaccounts (список без {id})
LOYALTY_CITY_READ / LOYALTY_CITY_WRITE GET /v1/admin/cities, GET /v1/admin/cities/{code} / POST /v1/admin/cities, PUT /v1/admin/cities/{code}, POST /v1/admin/cities/{code}/status
LOYALTY_STORE_READ / LOYALTY_STORE_WRITE GET /v1/admin/stores, GET /v1/admin/stores/{code} / POST /v1/admin/stores, PUT /v1/admin/stores/{code}, POST /v1/admin/stores/{code}/status
LOYALTY_MERCHANT_READ / LOYALTY_MERCHANT_WRITE GET /v1/admin/merchants, GET /v1/admin/merchants/{code} / POST /v1/admin/merchants, PUT /v1/admin/merchants/{code}, POST /v1/admin/merchants/{code}/status
LOYALTY_PRODUCT_CATALOG_READ GET /v1/admin/product-categories, GET /v1/admin/product-categories/{code}, GET /v1/admin/product-items, GET /v1/admin/product-items/{code}
LOYALTY_PRODUCT_CATALOG_WRITE POST /v1/admin/product-categories, PUT/DELETE /v1/admin/product-categories/{code}, POST .../{code}/status, POST /v1/admin/product-categories/import, POST .../import/validate; то же для /v1/admin/product-items

Мониторинг, бизнес-день, аудит, отчёты, сверка

Роль Метод и путь
LOYALTY_MONITORING_READ GET /v1/monitoring/summary\|anomalies\|expiring\|manual-accruals, GET /v1/customers/{externalId}/operations, GET /v1/business-day, GET /v1/business-day/{date}/summary, GET /v1/reports/pulse\|points\|tiers\|referrals, GET /v1/reports/promotions, GET /v1/reports/promotions/totals, GET /v1/reports/promotions/export, GET /v1/reports/promotions/{rootId}/dynamics, GET /v1/admin/audit, GET /v1/admin/audit/integrity, GET /v1/admin/audit/export, GET /v1/admin/reconciliation/runs, GET /v1/admin/reconciliation/runs/{runId}/diffs
LOYALTY_BUSINESS_DAY_WRITE POST /v1/business-day/close

Очередь приёма и исходящие уведомления

Роль Метод и путь
LOYALTY_INTAKE_WRITE POST /v1/intake/commands (подача), POST /v1/admin/intake/commands/{eventId}/retry\|cancel\|discard
LOYALTY_INTAKE_READ GET /v1/admin/intake/commands, GET /v1/admin/intake/commands/{eventId}
LOYALTY_NOTIFICATION_READ GET /v1/admin/notifications
LOYALTY_NOTIFICATION_WRITE POST /v1/admin/notifications/{id}/retry, POST /v1/admin/notifications/{id}/discard

Обмен данными

Роль Метод и путь
LOYALTY_EXCHANGE_READ GET /v1/admin/data-exchange/feeds/customers\|operations\|accounts, GET /v1/admin/data-exchange/jobs, GET /v1/admin/data-exchange/jobs/runs
LOYALTY_EXCHANGE_WRITE PATCH /v1/admin/data-exchange/jobs/{code}, POST /v1/admin/data-exchange/jobs/{code}/runs

Интеграции

Роль Метод и путь
LOYALTY_INTEGRATION_READ GET /v1/integration/pos/cards/{cardId}, GET /v1/integration/checkscan/customers/{externalId}, GET /v1/integration/customers/{externalId}/segments, POST /v1/integration/rtflow/condition-checks
LOYALTY_INTEGRATION_WRITE POST /v1/integration/pos/receipts, POST /v1/integration/pos/returns, POST /v1/integration/pos/returns/{returnId}/cancel, POST /v1/integration/rtflow/accruals, POST /v1/integration/promo/accruals, POST /v1/integration/promo/accruals/reversals, POST /v1/integration/partner/transactions, POST /v1/admin/reconciliation/external-totals

Гейтинг прав в UI (RBAC)

С выпуска 26.0.0 ролевая модель явно отражается в интерфейсе: все кнопки изменяющих действий (create / edit / merge / назначение уровня / импорт акций / настройка лимитов и т. п.) неактивны у пользователя без соответствующей роли LOYALTY_*_WRITE (для запуска акции — LOYALTY_PROMOTION_ACTIVATE, для согласования — LOYALTY_PROMOTION_APPROVE, для активации конфигурации — LOYALTY_PROGRAM_CONFIG_ACTIVATE). На недоступной кнопке показывается тултип-подсказка с указанием требуемой роли.

Разделы с собственной read-ролью закрываются целиком экраном «Нет доступа к разделу» с перечнем недостающих ролей вместо попытки загрузки данных:

Раздел Нужная роль
«Акции» LOYALTY_PROMOTION_READ
«Клиенты» LOYALTY_CUSTOMER_READ
«Ручные операции» Хотя бы одна из LOYALTY_ACCRUAL_WRITE, LOYALTY_REDEMPTION_WRITE, LOYALTY_TIER_WRITE, LOYALTY_CUSTOMER_TAG_WRITE (write-driven экран: вкладки операций без права скрыты)
«Конфигурации программы» LOYALTY_PROGRAM_CONFIG_READ
«Мониторинг», «Отчёты» LOYALTY_MONITORING_READ
«Справочники» → «Теги клиентов» / «Метки акций» / «Сегменты клиентов» LOYALTY_TAG_READ / LOYALTY_PROMOTION_LABEL_READ / LOYALTY_SEGMENT_READ

У «Настройки ПЛ» и подразделов «Администрирования» общей проверки на входе нет: они собраны из блоков под разными ролями, и каждый блок сам сообщает об отказе. Это упреждающая проверка для удобства оператора; итоговая проверка прав выполняется на бэкенде — при отсутствии роли API возвращает 403 независимо от состояния UI.

UI-гейтинг не заменяет серверную проверку

Неактивная кнопка или закрытый раздел в интерфейсе — это подсказка, а не граница безопасности. Источником истины остаётся @PreAuthorize на бэкенде: даже прямой вызов API без нужной роли будет отклонён (403).

Группа LOYALTY_ADMINS

В Keycloak заведена одна группа LOYALTY_ADMINS, объединяющая все роли LOYALTY_*, кроме технических, которые предназначены интеграционным клиентам, а не операторам из Core UI:

  • LOYALTY_INTEGRATION_READ
  • LOYALTY_EXCHANGE_READ, LOYALTY_EXCHANGE_WRITE
  • LOYALTY_SEGMENT_INTAKE — выдаётся только учётной записи Batch Flow

Членство в LOYALTY_ADMINS — стартовая точка для реального заказчика (полный доступ оператора/администратора), а не рекомендация выдавать всё разом каждому пользователю: набор внутри группы дальше сузить нельзя, поэтому для персон с ограниченным доступом (см. ниже) роли выдаются точечно, а не через группу.

Предупреждения о повторном провижининге realm

Часть ролей заведена в Keycloak позже базового набора. Если realm уже провижинен старой версией import-loyalty-roles*.cfg, до перезапуска import.sh соответствующая функциональность будет отвечать 403 access_denied, даже когда бэкенд обновлён:

Роли Что не будет работать до перезапуска import.sh
LOYALTY_TAG_READ/WRITE, LOYALTY_CUSTOMER_TAG_WRITE, LOYALTY_PROMOTION_LABEL_READ/WRITE Справочник тегов, справочник меток акций, присвоение тегов клиентам, простановка меток на акции
LOYALTY_INTAKE_READ/WRITE Экран «Очередь приёма» — «Вернуть в работу», «Отменить»
LOYALTY_TIER_WRITE Ручное назначение уровня клиенту, перевод уровня в «Ручных операциях», параметры уровня
LOYALTY_PROMOTION_ACTIVATE, LOYALTY_PROMOTION_APPROVE Запуск акции (одиночный и массовый), согласование запуска
LOYALTY_PROGRAM_CONFIG_READ/WRITE/ACTIVATE Раздел «Конфигурации программы» целиком
LOYALTY_SEGMENT_READ/WRITE/INTAKE Экран «Сегменты клиентов», приём сегментов из Batch Flow
LOYALTY_CITY_*, LOYALTY_STORE_*, LOYALTY_MERCHANT_*, LOYALTY_PRODUCT_CATALOG_* Справочники городов, торговых точек, мерчантов и каталога товаров
LOYALTY_CLIENT_PROFILE_ACTIVATE, LOYALTY_CLIENT_PROFILE_DELETE Активация и удаление версий настройки карточки клиента
LOYALTY_ACHIEVEMENT_READ/WRITE Экран «Достижения», пересчёт бейджей клиента
LOYALTY_NOTIFICATION_READ/WRITE Разбор очереди исходящих уведомлений

BREAKING: запуск акции выведен из-под LOYALTY_PROMOTION_WRITE

POST /v1/promotions/{id}/activate и POST /v1/promotions/bulk-activate требуют LOYALTY_PROMOTION_ACTIVATE — всегда, независимо от того, включено ли согласование. До выкатки перезапустите import.sh (роли LOYALTY_PROMOTION_ACTIVATE и LOYALTY_PROMOTION_APPROVE заводятся на клиенте frontend и попадают в LOYALTY_ADMINS) и выдайте LOYALTY_PROMOTION_ACTIVATE группам, которые сегодня запускают акции правом записи, — иначе «Запустить» будет отвечать 403 access_denied. LOYALTY_PROMOTION_APPROVE выдаётся согласующим — другим людям, чем авторы акций.

BREAKING: LOYALTY_CORRECTION_OTHER_WRITE → LOYALTY_OPERATION_REASON_OTHER_WRITE

Роль, дающая право на причину «Прочее» в ручных операциях, переименована решением продукта от 2026-09-11 (право относится к значению справочника «Прочее», а не только к корректировке — им уже пользуются и начисление, и перевод уровня). На realm, провижиненном со старым именем LOYALTY_CORRECTION_OTHER_WRITE, старую роль нужно снять вручную — перезапуск import.sh только заводит новую LOYALTY_OPERATION_REASON_OTHER_WRITE, не переименовывает существующую. Пока это не сделано, любая ручная операция (одиночная и пакетная) с причиной «Прочее» будет отдавать 403 access_denied тем, у кого была только старая роль.

Рекомендуемые наборы ролей по персонам

Принцип наименьших привилегий

Выдавайте пользователю только те роли, которые нужны для его задач.

Персона Роли
Оператор поддержки клиентов LOYALTY_CUSTOMER_READ, LOYALTY_CUSTOMER_WRITE, LOYALTY_PROFILE_READ, LOYALTY_ACCOUNT_READ, LOYALTY_MONITORING_READ (карточка клиента требует его вместе с PROFILE_READ), LOYALTY_TAG_READ, LOYALTY_CUSTOMER_TAG_WRITE
Оператор ручных операций Набор выше плюс любые из LOYALTY_ACCRUAL_WRITE / LOYALTY_REDEMPTION_WRITE / LOYALTY_TIER_WRITE / LOYALTY_CUSTOMER_TAG_WRITE по кругу разрешённых операций; для операций с баллами и уровнем обязательно LOYALTY_DICTIONARY_READ (иначе форма причины не откроется); LOYALTY_OPERATION_REASON_OTHER_WRITE — только доверенным операторам
Маркетолог LOYALTY_PROMOTION_READ, LOYALTY_PROMOTION_WRITE, LOYALTY_PROMOTION_LABEL_READ, LOYALTY_PROMOTION_LABEL_WRITE (по умолчанию — обе на метки), LOYALTY_TAG_READ (условия по тегам), LOYALTY_SEGMENT_READ (экран сегментов; вход в него из реестра справочников требует ещё LOYALTY_DICTIONARY_READ), LOYALTY_ACHIEVEMENT_READ, LOYALTY_ACHIEVEMENT_WRITE; LOYALTY_PROMOTION_ACTIVATE — тем, кто запускает акции
Согласующий акций LOYALTY_PROMOTION_READ, LOYALTY_PROMOTION_APPROVE — не тем же людям, что готовят акции
Администратор программы LOYALTY_PROGRAM_CONFIG_READ, LOYALTY_PROGRAM_CONFIG_WRITE, LOYALTY_PROGRAM_CONFIG_ACTIVATE (активацию можно выдать отдельно), LOYALTY_TIER_READ, LOYALTY_TIER_WRITE, LOYALTY_PROMOTION_READ; LOYALTY_PROMOTION_WRITE — если конфигурация назначает акции уровням
Аналитик / дежурная смена мониторинга LOYALTY_MONITORING_READ (мониторинг и раздел «Отчёты»)
Администратор НСИ LOYALTY_DICTIONARY_READ, LOYALTY_DICTIONARY_WRITE, LOYALTY_TAG_WRITE, LOYALTY_PROMOTION_LABEL_WRITE, LOYALTY_SEGMENT_READ, LOYALTY_SEGMENT_WRITE, LOYALTY_CITY_*, LOYALTY_STORE_*, LOYALTY_MERCHANT_*, LOYALTY_PRODUCT_CATALOG_*; LOYALTY_CLIENT_PROFILE_ACTIVATE и LOYALTY_CLIENT_PROFILE_DELETE — тем, кто применяет и чистит версии настройки карточки клиента
Администратор / эксплуатация LOYALTY_BUSINESS_DAY_WRITE, LOYALTY_MAINTENANCE_WRITE, LOYALTY_INTAKE_READ, LOYALTY_INTAKE_WRITE, LOYALTY_NOTIFICATION_READ, LOYALTY_NOTIFICATION_WRITE
Интеграция POS / Check Scan / RT Flow LOYALTY_INTEGRATION_READ, LOYALTY_INTEGRATION_WRITE, LOYALTY_EVENT_WRITE, LOYALTY_INTAKE_WRITE — по фактически используемым эндпоинтам конкретного клиента, не все сразу
Интеграция Batch Flow (сегменты) LOYALTY_SEGMENT_INTAKE
Интеграция обмена данными / DWH LOYALTY_EXCHANGE_READ, LOYALTY_EXCHANGE_WRITE

Гранулярность денежных операций — в дорожной карте

Сейчас пополнение, списание, перевод и обмен баллов между счетами леджера (/top-up, /withdraw, /transfer, /exchange) разделяют единую роль LOYALTY_OPERATION_WRITE. При необходимости её можно разбить на отдельные роли по типам операций без изменения существующего контракта.