Перейти к основному содержимому
Разделы документации
Документация›Инженерия контента›4. Мапперы: входящие и исходящие

Мапперы: входящие и исходящие

Содержание

Почему это важно. Классификатор решает, какого рода инцидент это событие; маппер решает, как он выглядит. Входящий маппер превращает сырой вендорский JSON, который попадает в SOARForge, в поля кейса, которые читают ваши аналитики — заголовок, severity, статус, адрес отправителя, целевой хост — сохраняя при этом нетронутый оригинал для аудита. Сделайте маппинг правильно — и аналитики видят чистый, единообразный кейс независимо от того, из какого из дюжины источников он пришёл; сделайте неправильно — и они таращатся на кейс с пустым заголовком и стеной неподписанных атрибутов.

Эта глава покрывает два направления маппера, когда и как именно входящий маппер отрабатывает во время ingest, полный редактор маппинга, грамматику путей и операторов, которую понимает маппер, как протестировать маппер сквозь и где на самом деле используются исходящие мапперы.


4.1. Концепция: два направления, одна модель полей

#

Маппер — это именованный, переиспользуемый объект, привязанный к бренду интеграции (source key коннектора) и направлению:

  • Входящий маппер — отрабатывает в момент ingest. Вход — сырой JSON события; выход — набор значений полей кейса. Это мост между схемой вендора и моделью кейса SOARForge.
  • Исходящий маппер — отрабатывает, когда изменение кейса зеркалится обратно в систему-источник. Вход — поля кейса; выход — payload, сформированный под вендора. Исходящие мапперы выполняются только для инстансов коннекторов с включённым зеркалированием (см. §4.12).

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

Хранилище кейса Что сюда попадает Задаётся
Встроенные колонки кейса (title, description, severity, status, tags, occurred, …) Встроенные цели маппера Правилами, целящими в name, details, severity, status, tags, occurred, category, owner, phase, …
custom_fields Каждая кастомная (не встроенная) цель, которую сопоставил маппер Правилами, целящими в machine-имя кастомного поля, напр. emailfrom
raw_json Неизменяемый исходный payload события Никогда не маппится — хранится дословно, всегда
labels Каждый сырой атрибут события, который маппер не сопоставил Автоматически — см. ниже

Неизменяемый оригинал хранится всегда. raw_json — это нетронутое событие, каким оно прибыло; маппер никогда его не переписывает. Всё, что маппер явно не сопоставляет, тоже не теряется — писатель ingest материализует каждый несопоставленный сырой атрибут в метку ({ type: "<path>", value }), так что ни одно поле молча не исчезает. Несопоставленные данные идут в labels, никогда в custom_fields — это пространство имён зарезервировано для полей, которые маппер сопоставил намеренно.


4.2. Когда запускается входящий маппер

#

Входящий маппер — это один этап конвейера ingest. Алерты входят через POST /ingest, ставятся в очередь на RabbitMQ, и воркер ingest обрабатывает каждый внутри одной транзакции базы данных. Порядок фиксирован:

  1. Построить конверт — воркер нормализует payload в канонический конверт: source, sourceInstance, sourceRef, payload (сырое событие) и производные скаляры (name, details, occurred).
  2. Правила pre-processing — опциональные правила, которые могут отбросить или подправить событие.
  3. Классифицировать — классификатор, привязанный к инстансу коннектора, отрабатывает первым и выбирает тип инцидента (или fallback incident type инстанса).
  4. Смаппить — затем отрабатывает входящий маппер, привязанный к тому же инстансу, ограниченный тем типом инцидента, который только что выбрал классификатор.
  5. Спроецировать и записать — вывод маппера проецируется в запись кейса и записывается: встроенные — в колонки кейса, кастомные цели — в custom_fields, оригинал — в raw_json, несопоставленные атрибуты — в labels.

Сначала классификатор, затем маппер для выбранного типа. Решение классификатора выбирает, какие правила маппера применяются. Вот почему у маппера есть и common-правила (гоняются для каждого типа инцидента), и specific-правила (гоняются, только когда кейс одного типа инцидента) — см. §4.4.

Как выбирается маппер — приоритет. Глобального маппера по умолчанию нет. Выбор целиком привязан к инстансу:

  • Каждый инстанс коннектора (конфигурация, которую вы задаёте в Settings → Integrations → Connectors → Advanced Settings → Incoming Mapper) держит incomingMapperId. Это маппер, который воркер ingest гоняет для событий с этого инстанса.
  • Если у разрешённого инстанса есть привязанный маппер с хотя бы одним правилом, воркер гоняет его. Иначе он откатывается к проекции только по конверту — задаются лишь встроенные из конверта (title, description, occurred), а каждый листовой атрибут становится меткой. Ни одно правило никогда не «отрабатывает наполовину».

Привязывайте маппер на инстансе. Маппер, существующий в реестре, сам по себе ничего не делает. Он участвует в ingest, только когда инстанс коннектора направляет свою настройку Incoming Mapper на него. Редактор маппинга может создать и сохранить эту привязку за вас, когда вы открываете его из инстанса коннектора (§4.4).


4.3. Где мапперы в интерфейсе

#

Маршрут: /admin/incident-types (Objects Setup → Incident Types & Pipelines, группа Classification) · Права: incident_types.view, incident_types.manage

К мапперам добираются с двух взаимодополняющих поверхностей:

  1. Реестр объектов маппинга — единая таблица, перечисляющая классификаторы и оба направления мапперов. Используйте её, чтобы просматривать, клонировать, удалять и открывать любой маппер, а также создавать новые. Разобрано в §4.9.
  2. Incoming Mapping Editor — живой, управляемый инстансом визуальный редактор, где вы фактически собираете входящий маппер по реальным данным событий. Разобран далее.

Открытие входящего маппера из реестра ведёт в визуальный редактор. Открытие исходящего маппера открывает более простой диалог таблицы правил (тот же диалог, что вы используете для его создания) — у исходящих мапперов нет живого JSON-дерева, потому что они гоняются по полям кейса, а не по входящим событиям.


4.4. Редактор входящего маппинга

#

Маршрут: /admin/incident-types?tab=classification&classificationTab=incident-mapper · Права: incident_types.view, incident_types.manage

Почему это важно. Именно здесь фактически происходит маппинг. Он кладёт реальный JSON события с одной стороны и поля кейса с другой и позволяет соединять их кликом или перетаскиванием — затем показывает точное значение, которое получило бы каждое поле, вычисленное тем же движком, что гоняется в момент ingest. Что вы видите в превью — то и получаете.

Редактор — это двухпанельное рабочее пространство под управляющим заголовком.

Элементы заголовка

#
Элемент Назначение
Mapper name Имя, под которым сохраняется объект-маппер.
Save mapper Сохранить маппер. Если вы открыли редактор из инстанса коннектора, сохранение также привязывает маппер к этому инстансу.
Branch (тип инцидента) Какому типу инцидента принадлежат specific-правила на экране.
Scope (Common / Specific) Редактируете ли вы правила, гоняющиеся для каждого типа (Common), или только для выбранного типа инцидента (Specific).
Connector / Instance Инстанс коннектора, из которого тянуть образцы событий и (опционально) к которому привязать маппер.
Data (Pull / Schema / Upload) Откуда берутся события превью: Pull живых событий из инстанса, генерировать Schema/образец события или Upload (вставить) свой JSON.
Pull (+ limit / sort) Забрать события превью; для живых pull выберите сколько и newest/oldest first.

Под элементами управления кнопки веток показывают число common-правил и число правил каждого релевантного типа инцидента; ветка, которую классификатор может произвести, но у которой пока нет правил, подсвечена, чтобы вы замечали пробелы покрытия. Сворачиваемая панель details резюмирует активную ветку, привязанный классификатор, источник превью, поля конверта интеграции и живое превью того, какие сырые атрибуты пока несопоставлены (и какие станут метками).

Левая панель — список целевых полей

#

Левая панель перечисляет каждое поле, в которое можно маппить, взятое из двух источников:

  • Встроенные цели — канонические поля кейса, которые распознаёт маппер: name (title), details (description), severity, status, tags, occurred, owner, phase, category, dueDate, closeNotes, closeReason, playbookId.
  • Поля инцидента — кастомные и системные поля инцидента, обнаруженные для бренда коннектора.

Список можно фильтровать (поле поиска), показывать только mapped или unmapped поля и добавлять ad-hoc кастомную цель, набрав её machine-имя. Два имени отклоняются намеренно: всё, что начинается с case. (устаревшая форма), и имена, принадлежащие конверту, — source / sourceInstance / sourceRef (ими владеет интеграция, а не маппер).

Кнопка Auto-map просит бэкенд оценить текущее событие против целевых полей и заполняет высоко-уверенные предложения путей, не перезаписывая маппинги, которые вы задали вручную.

Правая панель — JSON события

#

Правая панель показывает текущее выбранное событие превью как цветокодированное дерево (значения окрашены по типу), сырое JSON-представление и вкладку guide с разобранными примерами путей. Поле поиска подсвечивает совпадающие ключи. Массивы показывают короткий образец своего содержимого, чтобы вы видели, что собираетесь маппить.

Маппинг поля: построчная строка и мастер

#

Каждое целевое поле — это строка. Чтобы его смаппить:

  1. Кликните Choose data path на строке (или кнопку {}), затем кликните нужное значение в JSON-дереве — или перетащите лист из дерева на строку. Выбранный путь заполняет поле источника строки.
  2. Строка Result: под строкой показывает значение, которое производит этот путь, после фильтров и трансформеров, вычисленное живой симуляцией превью.

Кнопка … (Filters & transformers) на сопоставленной строке открывает встроенный мастер, меню из трёх строк:

Строка мастера Что настраивает
Get Путь источника (пере-открывает выбор пути).
Where Цепочку фильтров, применяемую к забранному значению (см. §4.6).
Transformers Цепочку трансформеров, применяемую после фильтров.

Иконка корзины на строке Get очищает всё правило (путь, фильтры, трансформеры и любые расширенные настройки). Добавление фильтра или трансформера открывает редактор цепочки: каждый шаг — пронумерованная карточка с выпадающим списком выбора оператора, описанием, динамически отрисованными вводами аргументов (текст, число, чекбокс или JSON-текстовая область в зависимости от оператора) и кнопкой удаления. Add filter / Add transformer дописывает шаг в конец цепочки; порядок карточек — порядок выполнения.

Переупорядочивание цепочки. Шаги выполняются сверху вниз в показанном порядке. Встроенный редактор позволяет добавить шаг (в конец), сменить оператор шага на месте и удалить шаг. Чтобы переупорядочить, удалите и пере-добавьте в нужном порядке.

Если тип сопоставленного значения источника не совпадает с типом целевого поля, строка показывает предупреждение с конкретным предложением исправления (например, добавить трансформер Join with comma или First item, чтобы подать текстовому полю значение из массива).


4.5. Синтаксис путей

#

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

  • Точечная нотация. payload.sender.emailAddress.address идёт по вложенным объектам ключ за ключом.
  • Префикс payload.. Поля события живут под payload.*. Редактор добавляет префикс автоматически, когда вы выбираете путь из дерева. Горстка скаляров конверта адресуется в корне вместо этого: source, sourceInstance, sourceRef, name, details, occurred.
  • Числовой индекс массива. Числовой ключ индексирует массив: payload.toRecipients.0.emailAddress.address берёт первого получателя.
  • Проекция массива. Нечисловой ключ, применённый к массиву, проецируется по каждому элементу и собирает результаты: payload.toRecipients.emailAddress.address возвращает адрес каждого получателя как массив (undefined-элементы отбрасываются).

Это вся грамматика. Нет wildcard (*), нет [*]-слайса и нет выражения/интерполяции внутри пути источника. Логика формования значений — включая выражения в стиле DT — живёт в цепочке трансформеров, а не в пути (трансформер DT резолвит выражение относительно уже забранного значения; он не часть резолвинга путей).


4.6. Фильтры (Where) и трансформеры

#

Каждое правило маппинга прогоняет забранное значение через фиксированный конвейер:

путь источника → Where (фильтры) → значение по умолчанию (если пусто) → Трансформеры → запись в цель

  • Where / фильтры отрабатывают первыми. Они урезают значение — отбрасывают пустые элементы, оставляют уникальные или первые элементы или оставляют только те элементы массива, что совпадают с условием. Если после фильтрации значение пусто, подставляется значение по умолчанию правила (если задано).
  • Трансформеры отрабатывают последними. Они переформовывают значение — обрезают пробелы, удаляют HTML, меняют регистр, разбивают/склеивают, форматируют даты, сопоставляют одну строку другой, извлекают индикаторы и многое другое.

Аргументы операторов. Операторы, которым нужны аргументы, экспонируют их в мастере как типизированные вводы. Обязательные аргументы помечены *. Аргумент regex валидируется при сохранении — невалидный или небезопасный (с катастрофическим бэктрекингом) паттерн отклоняется заранее, а не падает молча в момент ingest.

Расширенное поведение на уровне правила (несётся на правиле, задаётся через диалог реестра):

Настройка Эффект
Overwrite policy always (по умолчанию), if_empty (только когда цель ещё пуста) или never (оставить существующее значение в покое).
Required Если правило не производит значения, ingest фиксирует предупреждение (кейс всё равно создаётся).
On error Если фильтр/трансформер бросает: skip_field (по умолчанию — оставить поле незаданным), use_raw_value, set_default или fail_rule.

Каталог операторов велик — 138 трансформеров (семейства string, array, object, date/time, math, encoding и security/IOC) плюс 10 фильтров (compact, drop_empty, unique, first, where_exists, where_equals, filter, If-Then-Else, RegexExtractAll, SetByIndex) — 148 записей реестра всего. Полный справочник — каждый оператор, его аргументы и его поведение — живёт в файле-спутнике mapper-operators-reference.ru.md; разобранный пример в §4.11 использует лишь горстку из них.

Один и тот же движок повсюду. Фильтры и трансформеры оцениваются одним общим движком, используемым воркером ingest, превью редактора и инструментами теста. «Приближения превью» нет — превью и есть рантайм.


4.7. Типы полей и приведение

#

Маппер не заставляет сопоставленное значение принять тип цели; он пишет то, что произвёл конвейер, а проектор кейса нормализует встроенные поля:

  • Severity нормализуется к одному из critical / high / medium / low / informational (без учёта регистра, пробелы в подчёркивания; info → informational). Числовая severity — число или числовая строка — отображается на шкалу по нижней границе диапазона: 0/0.5 → informational, 1 → low, 2 → medium, 3 → high, ≥ 4 → critical (значения выше шкалы обрезаются; дробные округляются вниз, так что 2.7 → medium). Только значение, которое не является ни распознанным термином, ни неотрицательным конечным числом, откатывается к severity по умолчанию типа инцидента.
  • Status нормализуется к одному из new / open / in_progress / pending_approval / resolved / closed, иначе откатывается к new. Числовой статус не приводится — единой межвендорной числовой конвенции статусов нет, поэтому числовой статус откатывается, а не угадывается. Отобразите его явно трансформером маппера (MapPattern) в принятый термин.
  • Tags принимают массив или строку через запятую; каждый становится обрезанным тегом.
  • Title ограничен 500 символами. Если на текстовое поле (title/description) маппится не-строковое значение, оно сериализуется в JSON-строку, а не отбрасывается — вот почему маппинг целого объекта на name производит JSON-кляксу как заголовок. Маппьте скалярный лист вместо этого.

Для кастомных полей приведения по схеме нет — значение хранится, как произведено. Вот почему важно предупреждение о несовпадении типа в редакторе: оно сигнализирует, например, о массиве, смапленном на одно-значное поле, чтобы вы могли вставить трансформер joinComma или first до сохранения.


4.8. Диалог правил маппера (реестр / исходящий)

#

Создание исходящего маппера или редактирование любого маппера из таблицы реестра без JSON-дерева использует диалог таблицы правил. Он экспонирует поля, которые визуальный редактор прячет за своим мастером, и это поверхность, где значения по умолчанию и сырые цепочки трансформеров вводятся напрямую:

Поле диалога Назначение
Mapper Name Имя маппера.
Integration Brand Source key коннектора, для которого этот маппер.
Schema Source Как маппер обнаружил свою форму: Instance / Schema / JSON sample.
Content Source System / Marketplace / Custom (новые мапперы по умолчанию Custom).
System denylist Имена атрибутов, никогда не материализуемые в метки автоматически (по умолчанию включают dbot_status, close_notes, …).
Enabled Участвует ли маппер.
Common Mapping rules Правила, гоняющиеся для каждого типа инцидента. Каждая строка: Target field, JSON path, Transformers (как JSON-вызовы операторов), Default value, Rule enabled.
Specific Mapping rules То же плюс Incident Type — правило гоняется только для этого типа.

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


4.9. Управление мапперами

#

Таблица реестра объектов маппинга перечисляет классификаторы и оба направления мапперов вместе. Колонки:

Колонка Значение
Name Кликните, чтобы открыть объект в его редакторе.
Type Classifier, Mapper (incoming) или Mapper (outgoing).
Instances Сколько инстансов коннекторов сейчас привязывают этот объект.
Description Сводка (для маппера: направление, число common-правил, число specific-типов).
System True, когда объект принадлежит system/marketplace (а не Custom).

Действия панели инструментов: Edit, Clone, Delete и меню New (New Incident Classifier / New Incoming Mapper / New Outgoing Mapper). Поле поиска фильтрует по имени, бренду или описанию.

Clone / duplicate. Clone копирует выбранный маппер в новый редактируемый объект: к имени добавляется суффикс (copy) ((copy 2), (copy 3), … при необходимости), правила копируются, а Content Source копии сбрасывается на Custom, так что маппер, принадлежащий system или marketplace, становится свободно редактируемым. Clone — рекомендуемый способ адаптировать поставленный маппер.

Мапперы, поставленные паком. Content-паки из Marketplace могут поставлять мапперы; они приходят помеченными как принадлежащие system/marketplace (Content Source не Custom), и реестр помечает их System: True. Предпочитайте Clone редактированию pack-owned маппера на месте — последующее обновление пака может перезаписать маппер, которым он владеет, отбросив правки на месте, тогда как ваш Custom-клон ваш и останется.

Удаление маппера. Маппер, который всё ещё привязан к одному или нескольким инстансам коннекторов, удалить нельзя — платформа отказывает с ошибкой конфликта. Сначала отвяжите его от каждого инстанса (очистите настройку Incoming/Outgoing Mapper инстанса).


4.10. Сквозное тестирование маппера

#

У вас есть две возможности проверки, и они проверяют разное.

1. Живое превью редактора. По мере сборки редактор непрерывно симулирует текущий собираемый маппер против выбранного события превью и показывает, по полям, точное значение, которое он произвёл бы (строка Result:), сырые атрибуты, всё ещё несопоставленные, и какие из них станут метками. Поскольку превью гоняет тот же движок, что и ingest, значение, появляющееся здесь, — это значение, которое получил бы реальный кейс. Вытяните несколько живых событий (или вставьте репрезентативное) и пройдитесь по ним, чтобы подтвердить, что маппер держится поперёк вариаций.

2. Вкладка Test. Objects Setup → Incident Types & Pipelines → Classification → Test (/admin/incident-types?tab=classification&classificationTab=test) гоняет весь фронт конвейера вместе: выберите коннектор и инстанс, вставьте образец payload ingest ({ source, sourceInstance, payload }) и Run Test. Результат показывает:

  • Classification — какой тип инцидента победил и по какому правилу (или fallback-тип), с построчной трассировкой условий.
  • Mapped Fields Preview — вывод маппера для разрешённого типа инцидента, поле за полем.

Это самый быстрый способ подтвердить, что классификатор и его маппер согласны — что тип, который выбирает классификатор, — это тип, чьи specific-правила вы ожидаете запустить.

Проверяйте, прежде чем полагаться. Тестируйте на реальных (или реалистичных) событиях, а не на идеализированном. Вендоры варьируют форму поля между видами алертов — адрес, который иногда строка, а иногда объект, severity, которое иногда числовое — и только реальный образец это вскрывает.


4.11. Разобранный пример

#

Допустим, коннектор почтового ящика Microsoft 365 доставляет отчёты о фишинге, и вы хотите чистый кейс Phishing. Репрезентативный payload события:

{
  "source": "o365",
  "sourceInstance": "o365-soc-mailbox",
  "payload": {
    "subject": "  Re: Invoice overdue — please verify  ",
    "severity": "High",
    "categories": ["phishing", "", "external"],
    "body": { "content": "<p>Click <a href='http://bad.example'>here</a></p>" },
    "sender": { "emailAddress": { "address": "Billing@BAD.example", "name": "Billing" } },
    "toRecipients": [
      { "emailAddress": { "address": "alice@corp.local", "name": "Alice" } },
      { "emailAddress": { "address": "bob@corp.local", "name": "Bob" } }
    ]
  }
}

Входящий маппер из шести правил (scope показан по строкам; все используют overwrite policy always):

# Путь источника Фильтры (Where) Трансформеры Целевое поле
1 payload.subject — trim name (заголовок кейса)
2 payload.severity — toLowerCase severity
3 payload.body.content — htmlToText details (описание)
4 payload.sender.emailAddress.address — toLowerCase emailfrom (custom)
5 payload.toRecipients.emailAddress.address — joinComma emailto (custom)
6 payload.categories compact — tags

Что производит каждое правило:

  1. Title → Re: Invoice overdue — please verify (пробелы обрезаны).
  2. Severity → high (в нижний регистр, затем нормализовано к enum).
  3. Description → HTML, ободранный до читаемого текста.
  4. emailfrom (custom) → billing@bad.example, хранится в custom_fields.
  5. emailto (custom) → alice@corp.local, bob@corp.local — проекция массива собирает оба адреса получателей, joinComma складывает их в одну строку.
  6. Tags → ["phishing", "external"] — compact отбрасывает пустую строку.

Всё, что шесть правил не сопоставили (например payload.sender.name), становится меткой на кейсе, а весь payload выше сохраняется дословно в raw_json. Каждый использованный здесь оператор (trim, toLowerCase, htmlToText, joinComma, compact) существует в каталоге операторов; об остальных см. mapper-operators-reference.ru.md и работу по операторному конвейеру в главе 5.


4.12. Исходящие мапперы

#

Исходящий маппер — зеркальное отражение: он отрабатывает, когда изменение кейса зеркалится обратно в систему-источник. Он привязан к outgoingMapperId инстанса коннектора и выполняется только для инстансов, чей режим зеркалирования — outgoing или both. Когда кейс создаётся или меняется зеркалируемое поле, платформа ставит в очередь задачу зеркалирования; сервис коннектора загружает привязанный исходящий маппер, проверяет его направление, гоняет его правила по полям кейса (тот же движок правил, что и у входящего) и передаёт получившийся payload интеграции для проталкивания наверх. Действие preview mirroring позволяет увидеть исходящий payload для конкретного кейса до включения потока.

Исходящие мапперы авторятся в диалоге таблицы правил (§4.8) — JSON-дерева нет, потому что «источник» — это кейс, а не входящее событие. Выражения путей, фильтры, трансформеры, значения по умолчанию и политики на уровне правил работают ровно так же, как во входящем.

Гоняется только то, что использует зеркалирование. Исходящий маппер, не привязанный к инстансу с включённым зеркалированием, инертен — он хранится и редактируется, но никакой рантайм-путь его не выполняет, пока инстанс не начнёт зеркалить через него.


Распространённые ошибки

#
  • Маппер сохранён, но в момент ingest ничего не меняется. Маппер гоняется, только когда инстанс коннектора его привязывает (Incoming Mapper в advanced settings инстанса). Непривязанные мапперы ничего не делают; инстанс откатывается к проекции только по конверту.
  • Обязательное поле выходит пустым. Классификатор выбирает тип инцидента, и только specific-правила этого типа гоняются рядом с common-правилами. Если поле смаплено только в specific-ветке для другого типа, оно не заполнится. Кладите type-агностичные маппинги в Common.
  • Путь резолвится в ничто. Следите за неверным префиксом (поля события под payload.*), массивом там, где вы ждали объект (используйте числовой индекс или положитесь на проекцию), или полем, которое присутствует в одном виде алерта и отсутствует в другом. Строка Result: редактора и панель несопоставленных полей показывают промахи немедленно.
  • Заголовок — JSON-клякса. Не-строковое значение, смапленное на name/details, сериализуется в JSON, а не отбрасывается. Маппьте скалярный лист или добавьте трансформер (напр. first, joinComma), чтобы свести массив/объект к тексту.
  • Severity или status «игнорируются». Эти встроенные нормализуются к фиксированному enum. Severity также принимает числовую шкалу (0→informational … ≥4→critical, §4.7); status числа не приводит. Значение вне набора (или числовой статус) откатывается к умолчанию — маппьте вендорское значение через трансформер MapPattern/SetIfEmpty, чтобы перевести его в принимаемый термин.
  • Редактирование pack-owned маппера. Правки на месте system/marketplace-маппера (System: True) могут быть перезаписаны более поздним обновлением пака. Сначала Clone его — копия Custom и её безопасно менять.
  • Маппер не удаляется. Он всё ещё привязан к инстансу коннектора. Очистите настройку маппера инстанса везде, где он используется, затем удаляйте.
  • Превью выглядело хорошо, но прод отличается. Проверяйте на реальных, разнообразных событиях. Движок превью идентичен рантайму, так что расхождение почти всегда означает, что живое событие отличается по форме от вашего образца.