Согласование изменений
Владелец рабочего пространства может потребовать, чтобы административные изменения подтверждали участники, прежде чем они применятся. Это отдельный механизм от аппрувов транзакций: правило задаётся на действие, а не политикой, и подтверждают его владелец, администраторы или выбранная группа.
По умолчанию согласование выключено. Владелец включает его для каждого действия отдельно.
Какие действия
| Действие | Что покрывает | operation в запросе |
|---|---|---|
| Управление пользователями | приглашение пользователя, создание API-пользователя, удаление пользователя и API-пользователя, смена роли, блокировка и разблокировка пользователя | create, api_user_create, delete, role_change, block, unblock |
| Управление группами | создание, переименование и удаление группы, состав участников | create, update, delete, add_members, remove_members |
| Управление согласованием | порог администраторов и правила согласования, включая их выключение | threshold, action_setting |
| Добавление адреса в белый список | новый адрес во внешнем кошельке | нет |
| Управление тегами | создание, изменение и удаление тега, привязка и отвязка тегов к аккаунтам | create, update, delete, attach_detach |
| Переводы на one-time адреса | разрешение и запрет переводов по адресу вне белого списка | нет |
| Управление политиками | изменение правил политики и откат к версии из истории | update, rollback |
Правило одно на действие: нельзя требовать согласования удаления, но не
смены роли. Изменения администратора платформы (PLATFORM_ADMIN)
согласования не требуют; у поддержки платформы (PLATFORM_SUPPORT) такого
обхода нет.
Кто подтверждает
| Режим | Значение mode |
Кто подтверждает |
|---|---|---|
| Владелец | QUORUM_APPROVAL_MODE_OWNER_ONLY |
владелец рабочего пространства |
| Кворум администраторов | QUORUM_APPROVAL_MODE_ADMIN_QUORUM |
администраторы, включая неподписывающих; порог общий для всех действий в этом режиме |
| Группа | QUORUM_APPROVAL_MODE_SPECIFIC_GROUP |
участники выбранной группы, чьей роли доступно мобильное приложение (все роли, кроме наблюдателя и оператора), со своим порогом |
К кворуму администраторов или группе можно добавить обязательное подтверждение владельца.
Режим «Группа» требует включённого согласования действия «Управление группами»; само это действие в режиме «Группа» включается.
| Изменение правил | Ответ |
|---|---|
| включить правило в режиме «Группа» или перевести на группу включённое, пока согласование действия «Управление группами» выключено | QUORUM_GROUP_MANAGEMENT_APPROVAL_DISABLED |
| выключить согласование действия «Управление группами», пока включено правило в режиме «Группа» | QUORUM_GROUP_MANAGEMENT_APPROVAL_IN_USE; в details.action_keys — ключи таких правил |
Подтверждение принимается только с привязанного устройства в мобильном приложении — это второй фактор. Инициатор тоже подтверждает свой запрос, владелец в режиме «Владелец» подтверждает сам.
Заблокировать рабочее пространство нельзя
Правила согласования подтверждает только владелец. Правило, состав
которого сейчас не набирает порог, включить нельзя: ответ
QUORUM_NO_ELIGIBLE_APPROVERS.
Порог администраторов не поднимается выше их числа, пока включено
правило в режиме кворума.
Настройки согласования меняет владелец. Администраторы, включая неподписывающих, могут предлагать изменения, пока владелец держит включённым согласование действия «Управление согласованием». Выключение этого согласования отменяет неподтверждённые запросы на изменение настроек.
| «Управление согласованием» | Изменение владельца | Изменение администратора |
|---|---|---|
| выключено (по умолчанию) | применяется сразу | не принимается: QUORUM_CHANGE_REQUESTS_DISABLED |
| включено | запрос на согласование, владелец подтверждает сам | запрос на согласование, подтверждает владелец |
Как проходит согласование
- Инициатор выполняет действие как обычно. Если для него включено
согласование, изменение не применяется, а ответ приходит с кодом
QUORUM_APPROVAL_REQUIREDи идентификатором запроса. - Тем, кто подтверждает, приходит push-уведомление на привязанное устройство. Они подтверждают или отклоняют запрос в мобильном приложении.
- Когда подтверждений достаточно, изменение проверяется заново и применяется само. Повторять действие не нужно.
- Отказ, после которого порог уже не набрать, закрывает запрос. Пока запрос ждёт голосов, его можно отменить. Запрос без нужных голосов истекает через 72 часа.
Состав тех, кто подтверждает, фиксируется при создании запроса и может только сокращаться. Кто потерял право подтверждать, исключается из запроса при ближайшем голосе или повторной отправке того же изменения: голосовать по нему он больше не может, даже вернув право, а его голос не засчитывается. До исключения запрос ещё виден ему в списке ждущих голоса.
Право подтверждать теряют, когда:
- сменилась роль или человека убрали из группы подтверждающих;
- отвязано последнее устройство, например при смене телефона: роль, которой нужно устройство, неактивна до новой привязки;
- пользователь заблокирован в рабочем пространстве или на платформе;
- аккаунт ждёт настройки двухфакторной аутентификации.
Запрос устаревает, если после создания у правила согласования изменились условие одобрения или порог либо после исключения выбывших порог уже не набрать. Устаревший запрос отменяется при первом голосе или повторной попытке того же изменения, и повторная попытка создаёт новый запрос. Пока запрос не устарел, повторная попытка возвращает его же.
| Статус | Значение |
|---|---|
PENDING |
ждёт подтверждений |
APPROVED |
подтверждений достаточно, изменение применяется |
EXECUTED |
изменение применено. Если применять к этому моменту уже нечего, правка тега, привязка уже привязанного тега, настройка one-time адресов, блокировка уже заблокированного и разблокировка уже разблокированного пользователя тоже закрываются EXECUTED — без изменений |
FAILED |
подтверждено, но применить нельзя; причина — в карточке запроса. Например: инициатор к этому моменту заблокирован, удалён из рабочего пространства или потерял права на это изменение, пользователь уже в этой роли или уже в группе, адрес уже в белом списке, рабочее пространство заморожено, тег уже отвязан, тег изменился после запроса, политика изменилась после запроса |
REJECTED |
отклонено |
EXPIRED |
72 часа прошли без нужных подтверждений |
CANCELLED |
отменено до решения: инициатором, владельцем или администратором, выключением согласования «Управления согласованием» (запросы на изменение настроек) или потому, что запрос устарел |
Ход согласования приходит событиями по WebSocket участникам согласования: инициатору, тем, кто подтверждает, и тем, кто видит все запросы рабочего пространства. На привязанное устройство события приходят только инициатору и тем, кто подтверждает. Каждое решение попадает в журнал аудита.
Просмотр изменений в мобильном приложении
Небольшое изменение — например, новый адрес в белом списке или правка нескольких полей одного правила политики без перемещения — показано прямо в карточке запроса в мобильном приложении: что было и что станет.
Если изменение большое, карточка показывает краткую сводку и кнопку «Посмотреть изменения». Кнопка открывает экран изменений с полным описанием «было → стало», добавленными и удалёнными значениями и пояснениями.
Подтверждают и отклоняют запрос в карточке: с экрана изменений вернитесь назад. У большого изменения кнопка «Подтвердить» доступна только после того, как экран изменений показал описание; отклонить можно сразу.
| Состояние | Что показано |
|---|---|
| Описание изменения ещё не загрузилось | сводка и кнопка «Посмотреть изменения»; «Подтвердить» — как у большого изменения |
| Описание изменения требует новой версии мобильного приложения | сводка, плашка «Обновите приложение, чтобы увидеть изменение целиком» и основные данные изменения; кнопки просмотра нет, «Подтвердить» доступна сразу |
| В изменении есть ослабление контроля (например, снятие запрета) или предупреждение | плашка в карточке: у большого изменения «Есть важные изменения: откройте их перед решением», у небольшого — «Есть важные изменения: проверьте их перед решением» над ним |
| Описания изменения нет | основные данные изменения в карточке, без «было → стало» |
| Описание изменения урезано | плашка «Показано не всё: описание урезано по размеру» на экране изменений |
| При открытии экрана изменений запрос уже не ждёт подтверждений или не найден | плашка «Запрос больше не ожидает решения»; описание, если оно есть, показано |
Одно изменение объекта за раз
Пока по объекту есть запрос в работе — он ждёт подтверждений или подтверждён
и применяется, — другое изменение того же объекта не принимается: ответ
CHANGE_REQUEST_IN_PROGRESS
с данными этого запроса.
| Объект | Что считается его изменением |
|---|---|
| политика транзакций | обновление правил и откат к версии из истории |
| правило согласования действия | изменение правила |
| порог кворума администраторов | изменение порога |
| пользователь | смена роли, блокировка, разблокировка, удаление |
| группа | изменение, удаление, добавление и удаление участников |
| тег | изменение и удаление; привязка и отвязка тегов объект не держат |
| one-time адреса рабочего пространства | разрешение и запрет |
| Изменение объекта, пока по нему есть запрос в работе | Ответ |
|---|---|
| другое изменение — и требующее согласования, и не требующее его сейчас | CHANGE_REQUEST_IN_PROGRESS |
| то же самое изменение, пока согласование включено и запрос ждёт подтверждений | как при регистрации: QUORUM_APPROVAL_REQUIRED с этим запросом |
изменение администратора платформы (PLATFORM_ADMIN) |
принимается, запрос остаётся в работе |
Чтобы изменить объект по-другому, запрос в работе нужно закрыть: дождаться решения или срока либо отменить его.
Отмена
| Кто | Что может отменить |
|---|---|
| инициатор | свой запрос |
| владелец | любой запрос рабочего пространства, который ждёт подтверждений |
| администраторы, включая неподписывающих | запрос действия, в правиле которого включено admins_can_cancel |
admins_can_cancel по умолчанию выключено; у правила «Управление
согласованием» его включить нельзя. Администратор может отменить и запрос,
который касается его самого. Подтверждения с устройства отмена не требует.
Для интеграции
Ответ на действие, которому нужно согласование:
{
"error": "change requires quorum approval",
"code": "QUORUM_APPROVAL_REQUIRED",
"details": {
"approval_request_uuid": "3f0c5c1e-…",
"action": "<action_key>",
"operation": "delete",
"mode": "QUORUM_APPROVAL_MODE_OWNER_ONLY",
"expires_at": "2026-09-17T10:00:00Z"
}
}
Ответ на изменение объекта, по которому есть запрос в работе:
{
"error": "another change request for this object is in progress",
"code": "CHANGE_REQUEST_IN_PROGRESS",
"details": {
"approval_request_uuid": "3f0c5c1e-…",
"action": "<action_key>",
"operation": "update",
"status": "PENDING",
"initiator_uuid": "7d1e…",
"initiator": { "user_uuid": "7d1e…", "user_type": "user", "email": "anna@example.com", "first_name": "Anna" },
"initiated_by_me": false,
"can_cancel": true,
"created_at": "2026-10-05T10:00:00Z",
"expires_at": "2026-10-08T10:00:00Z"
}
}
Поле details |
Когда есть |
|---|---|
expires_at |
у запроса в PENDING |
initiator_uuid, initiator |
только если вызывающему доступна карточка запроса — он участник запроса или у него VIEW_CHANGE_APPROVALS; initiator может отсутствовать и у них |
can_cancel |
может отсутствовать |
Ключ действия отдаёт GET …/quorum/actions полем key, в ответе на
действие он приходит полем action. Режим везде передаётся значением из
таблицы режимов: в ответе на действие, в запросах согласования и в
настройках.
| Ответ действия | Когда |
|---|---|
403 QUORUM_APPROVAL_REQUIRED |
правило включено; запрос зарегистрирован, его данные — в details |
409 QUORUM_NO_ELIGIBLE_APPROVERS |
правило включено, но подтверждать сейчас некому; изменение не сохраняется |
409 CHANGE_REQUEST_IN_PROGRESS |
по объекту изменения уже есть запрос в работе, см. Одно изменение объекта за раз; изменение не сохраняется, в details — этот запрос |
503 CHANGE_APPROVAL_UNAVAILABLE |
согласование временно недоступно; изменение не сохраняется, повторите позже |
| Метод | Путь | Право |
|---|---|---|
GET |
/api/v2/admin/tenants/{tenant_uuid}/change-approvals?scope=PENDING_MY_VOTE\|INITIATED_BY_ME\|ALL |
пользователь рабочего пространства; ALL — VIEW_CHANGE_APPROVALS; с привязанного устройства — только PENDING_MY_VOTE и INITIATED_BY_ME пользователя, привязавшего устройство к этому рабочему пространству |
GET |
/api/v2/admin/change-approvals?scope=… — тот же список сразу по всем рабочим пространствам, доступным токену; страница общая |
как у списка рабочего пространства, по каждому пространству отдельно; ALL — только пространства с VIEW_CHANGE_APPROVALS, ни одного — 403 |
GET |
…/change-approvals/{request_uuid} |
участник запроса или VIEW_CHANGE_APPROVALS; с устройства — участник |
POST |
…/change-approvals/{request_uuid}/approve, …/reject |
участник согласования, с привязанного устройства |
POST |
…/change-approvals/{request_uuid}/cancel |
инициатор запроса, владелец и, если правило действия это разрешает (admins_can_cancel), администраторы, см. Отмена; с привязанного устройства — если роль требует привязки устройства |
GET |
/api/v2/admin/tenants/{tenant_uuid}/quorum |
VIEW_QUORUM_SETTINGS |
GET |
…/quorum/actions — список действий: ключ key (он же {action_key} в пути PUT) и fixed_mode у действия, режим которого не выбирается |
VIEW_QUORUM_SETTINGS |
PUT |
…/quorum/actions/{action_key}, …/quorum/threshold |
MANAGE_QUORUM_SETTINGS; PROPOSE_QUORUM_SETTINGS — только запросом, пока включено «Управление согласованием» |
GET |
…/quorum/gated-actions — действия рабочего пространства и requires_approval: потребует ли действие у вызывающего согласования; предупреждение до отправки изменения, прав на настройки не требует |
пользователь или API-пользователь с активной ролью в рабочем пространстве; с устройства — 403 |
Устройству, привязанному в нескольких рабочих пространствах, хватает одного
запроса: у каждого элемента списка своё пространство в tenant_uuid и
tenant_name, а initiated_by_me считается по пользователю, привязавшему
устройство к этому пространству. Карточка и голос — по путям пространства
элемента.
Голос подписывается ключом привязанного устройства, который открывается
биометрией или ключом безопасности. В теле approve и reject приложение
передаёт signed_vote — JSON голоса в base64 — и signature, подпись
Ed25519 этих байтов, тоже в base64:
{"type": "change_vote", "tenant_uuid": "…", "request_uuid": "3f0c5c1e-…",
"vote": "approve", "device_uuid": "…", "changes_hash": "9f2c…"}
changes_hash — отпечаток описания из карточки, по которой голосуют, пусто
без описания. Голос approve засчитывается, только если он совпадает с
changes_hash запроса; reject — при любом.
GET /api/v2/admin/change-approvals?scope=PENDING_MY_VOTE&limit=50
{
"items": [
{ "request_uuid": "3f0c5c1e-…", "tenant_uuid": "0f8b7a5e-…", "tenant_name": "Treasury",
"action": "<action_key>", "action_display_name": "Manage users", "status": "PENDING", "initiated_by_me": false },
{ "request_uuid": "a91d07b2-…", "tenant_uuid": "7c2e41d9-…", "tenant_name": "Trading",
"action": "<action_key>", "action_display_name": "Manage tags", "status": "PENDING", "initiated_by_me": true }
],
"total": 2,
"limit": 50,
"offset": 0
}
Ответ на принятый голос и на отмену — обновлённая карточка запроса. Отмена
переводит в CANCELLED запрос, открытые sets[] и неподанные голоса,
поданные голоса остаются; кто и почему отменил — в cancelled_by и
cancel_reason.
POST /api/v2/admin/tenants/{tenant_uuid}/change-approvals/3f0c5c1e-…/cancel
{
"request": {
"request_uuid": "3f0c5c1e-…",
"status": "CANCELLED",
"cancel_reason": "owner",
"cancelled_by": { "user_uuid": "5b2f…", "user_type": "user", "email": "boss@example.com" },
"sets": [
{ "external_id": "OWNER", "threshold": 1, "status": "CANCELLED",
"approvers": [ { "user_uuid": "5b2f…", "status": "CANCELLED", "is_me": false } ] }
]
}
}
| Ответ | На что | Когда |
|---|---|---|
CHANGE_VOTE_DEVICE_REQUIRED |
approve, reject |
голос не с привязанного устройства |
CHANGE_VOTE_SIGNATURE_REQUIRED |
approve, reject |
голос не подписан ключом устройства: версия приложения устарела, его нужно обновить |
CHANGE_VOTE_SIGNATURE_INVALID |
approve, reject |
голос подписан не ключом этого устройства или подписан другой голос; у approve — и подписанный changes_hash не совпадает с запросом |
CHANGE_VOTE_NOT_ALLOWED |
approve, reject |
голосующий не входит в состав подтверждающих запроса или исключён из него, потеряв право подтверждать |
CHANGE_VOTE_CONFLICT |
approve, reject |
противоположный голос уже подан; повтор того же голоса ничего не меняет |
CHANGE_REQUEST_CANCEL_NOT_ALLOWED |
cancel |
нет права отменить запрос, см. Отмена |
200, та же карточка |
cancel |
запрос уже отменён |
CHANGE_REQUEST_ALREADY_FINALIZED |
все три | запрос уже закрыт или истёк; на голос — и когда запрос устарел: у правила согласования изменились условие одобрения или порог либо состав изменился так, что порог уже не набрать. Запрос при этом отменяется |
CHANGE_REQUEST_NOT_FOUND |
все три | запроса нет в рабочем пространстве; то же у карточки |
Карточка запроса несёт всё, что нужно показать человеку, без дополнительных запросов:
{
"request": {
"request_uuid": "3f0c5c1e-…",
"tenant_uuid": "…",
"tenant_name": "Treasury",
"action": "<action_key>",
"action_display_name": "Manage users",
"initiator": { "user_uuid": "7d1e…", "user_type": "user", "email": "owner@example.com", "first_name": "Anna", "last_name": "Smirnova", "api_user_name": "" },
"initiated_by_me": false,
"can_cancel": true,
"cancel_reason": "",
"payload": { "operation": "delete", "tenant_uuid": "…", "user_uuid": "9a4c…" },
"display": { "user": { "user_uuid": "9a4c…", "user_type": "user", "email": "ivan@example.com", "first_name": "Ivan" }, "current_role": "EDITOR" },
"status": "PENDING",
"summary": {},
"changes_hash": "",
"entities": {},
"sets": [
{
"external_id": "OWNER",
"threshold": 1,
"status": "PENDING",
"approvers": [ { "user_uuid": "5b2f…", "status": "PENDING", "user": { "user_uuid": "5b2f…", "user_type": "user", "email": "boss@example.com", "first_name": "", "last_name": "", "api_user_name": "" }, "is_me": true } ]
}
]
}
}
| Поле | Что содержит |
|---|---|
initiator, sets[].approvers[].user |
участник: user_type — user или api_user; у пользователя email, first_name, last_name, у API-пользователя api_user_name |
initiated_by_me, sets[].approvers[].is_me |
этот участник — вы; с привязанного устройства — пользователь, привязавший его к этому рабочему пространству |
can_cancel |
вы можете отменить запрос сейчас, см. Отмена; есть и в списке |
cancel_reason |
почему запрос в CANCELLED: initiator, owner, admin — отменил человек; rule_changed, approvers_changed — запрос устарел; change_requests_disabled — выключено «Управление согласованием». Пусто у запросов, отменённых раньше, чем появилось поле |
cancelled_by |
кто отменил, участник, как initiator; поля нет, если запрос устарел |
payload |
что будет изменено |
display |
названия и имена того, на что ссылается payload, на момент создания запроса; поля нет, если снимка нет |
summary |
однострочная сводка изменения по локалям шаблона, en есть всегда; есть и в списке; пусто, если описания изменения нет |
changes |
описание изменения «было → стало» на момент создания запроса; в карточке и ответах на голос и отмену; поля нет, если описания нет |
changes_hash |
отпечаток changes: меняется вместе с ним; клиент его не вычисляет, а только сравнивает; есть и в списке, пусто без описания |
entities |
пользователи, сервисные аккаунты и группы из changes — свежие на момент ответа: ключ "<kind>:<id>" (kind — user, service_account, user_group), значение — name, subtitle (email), subtype (user или api_user), is_me, missing; там же, где changes, иначе пустой объект |
| Действие | operation |
Поля display |
|---|---|---|
| Управление пользователями | role_change, delete, block, unblock |
user, current_role |
| Управление группами | update, delete |
group_name |
add_members, remove_members |
group_name, users — по порядку payload; у длинного списка только первые участники |
|
| Управление согласованием | action_setting |
action_display_name, group_name |
| Добавление адреса в белый список | нет | whitelisted_wallet_name, currency_symbol, currency_descriptor, blockchain_name |
| Управление тегами | update, delete |
tag |
attach_detach |
vaults, tags |
|
| Управление политиками | update |
policy_type_name |
rollback |
policy_type_name, version_published_at |
Остальные операции приходят без display: их payload читается как есть.
Состав подтверждающих в ответе настроек:
| Поле | Что содержит |
|---|---|
approver_sets, reachable у правила |
кто подтверждал бы сейчас и набирает ли состав порог; есть и у выключенных правил |
owner_approvers, admin_quorum_approvers |
кто прямо сейчас подтверждает как владелец и как администратор, независимо от правил |
active_member_uuids у группы в списке групп |
участники, которые считаются в режиме «Группа» |
Состав ещё не сохранённого правила считается из этих пулов, участников группы и порога.
Описание изменения
changes описывает изменение так, что его можно показать, не зная схемы
payload действия: секции (например, правила политики) с полями «было» и
«стало». Его присылают управление политиками (update, rollback),
управление тегами (все операции), добавление адреса в белый список и
управление one-time адресами. Запрос без описания (остальные действия, а у
перечисленных — если описание не собралось) приходит без поля changes, с
пустыми summary и changes_hash: показывайте его по display.
Пример — фрагмент карточки с описанием изменения правила политики:
выросла сумма и изменился набор аппруверов A (остальные поля карточки, поля
со значениями по умолчанию и часть шаблонов texts опущены):
{
"request": {
"request_uuid": "3f0c5c1e-…",
"changes": {
"schema_version": 1,
"summary": { "code": "policy.summary.update.transfer", "args": { "rules": "1" } },
"sections": [
{
"id": "5b0d2f1c-…", "kind": "policy.rule", "op": "CHANGE_VIEW_OP_MODIFIED",
"title": { "code": "policy.rule.title", "args": { "name": "Large transfers" } },
"position_before": 3, "position_after": 1,
"fields": [
{ "id": "amount", "label": { "code": "policy.field.amount" }, "op": "CHANGE_VIEW_OP_MODIFIED",
"before": { "money": { "amount": "1000", "currency": "USD" } },
"after": { "money": { "amount": "5000", "currency": "USD" } } },
{ "id": "approval.sets.A.members", "op": "CHANGE_VIEW_OP_MODIFIED",
"label": { "code": "policy.field.approval.set.members", "args": { "set": "A" } },
"after": { "set": { "items": [
{ "op": "CHANGE_VIEW_OP_ADDED", "value": { "entity": { "kind": "user_group", "id": "33f1…" } } }
] } } },
{ "id": "approval.sets.A.threshold", "op": "CHANGE_VIEW_OP_MODIFIED", "important": true,
"label": { "code": "policy.field.approval.set.threshold", "args": { "set": "A" } },
"before": { "number": "2" }, "after": { "number": "1" } }
]
}
],
"notes": [ { "severity": "CHANGE_VIEW_NOTE_SEVERITY_INFO", "text": { "code": "policy.note.order.transfer" } } ],
"texts": {
"policy.summary.update.transfer": { "by_locale": { "en": "Transfers policy: {rules} rule(s) affected", "ru": "Политика переводов: затронуто правил — {rules}" } },
"policy.field.amount": { "by_locale": { "en": "Amount from", "ru": "Сумма от" } }
}
},
"summary": { "en": "Transfers policy: 1 rule(s) affected", "ru": "Политика переводов: затронуто правил — 1" },
"changes_hash": "9f2c…",
"entities": { "user_group:33f1…": { "name": "Finance" } }
}
}
Поле changes |
Что содержит |
|---|---|
summary |
однострочная сводка — текст |
fields |
поля верхнего уровня — у простых изменений (порог 2 → 3) |
sections |
секции — у составных изменений, в порядке показа; у секции id, kind (подсказка для особого показа, например policy.rule), title, op, позиции, fields, вложенные sections, notes и hidden_unchanged — сколько неизменённых полей и секций не перечислено |
notes |
пояснения и предупреждения: severity — CHANGE_VIEW_NOTE_SEVERITY_INFO или CHANGE_VIEW_NOTE_SEVERITY_WARNING; пустое значение и CHANGE_VIEW_NOTE_SEVERITY_UNSPECIFIED показываются как CHANGE_VIEW_NOTE_SEVERITY_INFO, незнакомое — как CHANGE_VIEW_NOTE_SEVERITY_WARNING; text |
truncated |
описание урезано по размеру и показывает не всё |
texts |
шаблоны текстов: код → by_locale → шаблон |
schema_version |
сейчас 1; у описания старшей версии показывается сводка, а само изменение — по display, как у запроса без описания |
Текст приходит кодом и аргументами (code, args). Шаблон кода берётся из
словаря клиента, иначе из texts на локали клиента, иначе на en, иначе
показывается сам код.
Подстановка — имя аргумента в фигурных скобках: строчные латинские буквы,
цифры и _. Она делается за один проход: {set} заменяется на args.set,
{…} внутри значения аргумента не раскрывается, подстановка без аргумента и
прочие скобки остаются как есть.
Значение аргумента — готовая строка, часто текст пользователя, например
название правила. Показывайте каждое значение изолированно от соседнего
текста, как элемент bdi в HTML: символы направления текста в нём не должны
переставлять остальную строку.
op |
Секция | Поле |
|---|---|---|
CHANGE_VIEW_OP_ADDED |
добавлена; position_before — 0 |
значение в after |
CHANGE_VIEW_OP_REMOVED |
удалена; position_after — 0 |
значение в before |
CHANGE_VIEW_OP_MODIFIED |
изменена; позиции могут различаться | before и after; у множества — after с элементами, отмеченными CHANGE_VIEW_OP_ADDED и CHANGE_VIEW_OP_REMOVED |
CHANGE_VIEW_OP_MOVED |
изменилась только позиция | — |
CHANGE_VIEW_OP_UNCHANGED |
без изменений, показана для контекста | значение в after |
important у поля — изменение ослабляет контроль: снятие запрета, снижение
порога.
| Вид значения | Что содержит |
|---|---|
text |
текст кодом и аргументами |
literal |
строка как есть: название, адрес |
flag, number |
да или нет; десятичное число |
money |
amount в валюте currency (USD) или, без currency, в единицах актива asset; при minor_units — в минимальных единицах актива |
entity |
сущность kind и id: имя — из entities карточки, если ключ там есть и не missing, иначе name снимка, а без него — id; subtitle — уточнение; missing — сущности нет; виды — в таблице ниже |
enum_value |
label для показа, code — значение |
set |
элементы items с value и op: в изменённом множестве — CHANGE_VIEW_OP_ADDED или CHANGE_VIEW_OP_REMOVED, элемент как есть — CHANGE_VIEW_OP_UNSPECIFIED или CHANGE_VIEW_OP_UNCHANGED; omitted — сколько элементов не перечислено |
list |
упорядоченный список items; omitted |
time, unset |
время; значение не задано |
| незнакомый вид | показывается строка fallback |
kind сущности |
Что это | Имя |
|---|---|---|
user, service_account, user_group |
пользователь, сервисный аккаунт, группа | свежее, в entities карточки |
vault |
аккаунт | снимок в name на момент создания запроса |
tag |
тег | снимок в name |
whitelisted_wallet |
кошелёк белого списка | снимок в name; subtitle — тип: internal, external, contract |
asset |
актив | снимок: name — символ, subtitle — сеть |