Перейти к содержимому

Плагины

Роутер умеет обрабатывать запрос дополнительными плагинами. Плагин включается на конкретный запрос через поле plugins в теле. Сейчас доступен DLP (data loss prevention).

DLP сканирует ввод пользователя на чувствительные данные (секреты и PII) и реагирует по выбранному режиму.

{
"model": "anthropic/claude-sonnet-4.6",
"messages": [{ "role": "user", "content": "мой email [email protected]" }],
"plugins": {
"dlp": {
"mode": "mask"
}
}
}

Поле plugins необязательное, но его отсутствие не отменяет проверку: у API-ключа бывает своя политика DLP, заданная администратором группы. См. Политика API-ключа.

mode Поведение
alert Найденное возвращается в ответе (plugins.dlp), запрос проходит как есть
mask Совпадения заменяются токенами перед отправкой в модель, в ответе восстанавливаются обратно
block Запрос отклоняется с 403 и кодом dlp_violation, в extra.dlp перечислены находки

Секреты и креды: ACCESS_TOKEN, API_KEY, BEARER_TOKEN, CERTIFICATE, JWT, PASSWORD, PRIVATE_KEY, PUBLIC_KEY, UNKNOWN_SECRET.

PII и идентификаторы: BANK_ACCOUNT, CREDIT_CARD, DOB, EMAIL, ID_NUMBER, IP_ADDRESS, MAC_ADDRESS, MEDICAL_ID, PHONE_NUMBER, POSTAL_CODE, SSN, SWIFT_BIC, TAX_ID, VEHICLE_VIN, а также российские KPP, OGRN, OGRNIP, OMS. Детекторы работают на EN и RU.

Поле необязательное. Без него проверяются все типы кроме UNKNOWN_SECRET: его находит анализ энтропии, а не шаблон, поэтому он даёт ложные срабатывания на длинных случайных строках и включается только явно. Если у ключа есть политика, без этого поля действуют её категории, а не полный список.

У API-ключа может быть политика DLP, заданная администратором группы. Она применяется как пол строгости: независимо от того, присылаете вы plugins.dlp или нет, запрос проверяется минимум по ней. У клиентов, написанных под стандарты OpenAI и Anthropic, поля для DLP-конфига нет вовсе, и на них политика тоже действует.

Ваш конфиг продолжает действовать, но только в сторону ужесточения:

Поле Что с ним делает объединение
mode Действует на правила, которые объявили вы. Если то же правило есть и в политике, побеждает более строгий режим: alert слабее mask, mask слабее block
entity_types Объединение категорий. Не прислали поле, действуют категории политики
stop_words Объединение списков запрещённых литералов
regexes Объединение списков собственных шаблонов
allowlist Действует только на находки по вашим правилам. Находку по правилу политики исключение не отменяет
report_scope Остаётся вашим, он выбирает только состав возвращаемых находок, а не решение о блокировке

Ещё два поля под политикой обнуляются: injected_context_names и acknowledged. Первое выводит помеченное сообщение из проверки, и под политикой это был бы способ от неё уклониться; второе и без политики ни на что не влияет.

Реакцию на находку задаёт тот, кто объявил сработавшее правило. Если вы перечислили entity_types, ваш режим действует на эти категории, на ваши стоп-слова и на ваши шаблоны, а по остальным категориям политики отвечает режим администратора. Если entity_types вы не прислали, ваш режим действует на все категории политики. Где правило объявлено с обеих сторон, побеждает более строгий режим.

Исключения подчиняются той же принадлежности: ваше исключение снимает находку по вашему правилу и не дотягивается до правила политики. Внутри вашего конфига запрет сильнее исключения: значение, объявленное и стоп-словом, и исключением, остаётся запрещённым.

Содержимое политики администратора вам не видно, и отдельной ошибки о том, что ваша настройка ослаблена, не приходит: применяется более строгая. Изменение настроек администратора доходит до проверки примерно за минуту.

Если политику ключа не удалось получить, запрос отклоняется с 503 и кодом dlp_policy_unavailable, а в заголовке Retry-After приходит интервал для повтора. Проверка не выключается сама: запрос без известной политики не уходит в модель.

Этот код отличается от dlp_unavailable, который тоже приходит с 503. Разница в реакции: dlp_policy_unavailable лечится повтором, а dlp_unavailable говорит, что DLP не включён, и повтор вернёт тот же ответ.

dlp_violation, /v1/chat/completions
{
"error": {
"code": "dlp_violation",
"message": "Request blocked: sensitive data detected",
"extra": {
"dlp": [
{
"category": "pii",
"entity_type": "EMAIL",
"message_index": 0,
"location": "messages[0].content",
"start": 12,
"end": 28,
"confidence": 0.98
}
],
"findings_count": 1,
"block_scope": "in_report_scope"
}
}
}

На /v1/messages тело в формате Anthropic: тип ошибки permission_error, машинный код рядом с ним в поле code, находки в details.

dlp_violation, /v1/messages
{
"type": "error",
"error": {
"type": "permission_error",
"code": "dlp_violation",
"message": "Request blocked: sensitive data detected",
"details": {
"dlp": [
{
"category": "pii",
"entity_type": "EMAIL",
"message_index": 0,
"location": "messages[0].content",
"start": 12,
"end": 28,
"confidence": 0.98
}
],
"findings_count": 1,
"block_scope": "in_report_scope"
}
}
}

Находка описывает место и класс совпадения: категория (secret, pii, custom), тип сущности, позиция в тексте. Самих значений в ней нет, и восстановить их по ответу нельзя. У находки по стоп-слову тип сущности STOP_WORD, по вашему шаблону CUSTOM_REGEX; категория у обоих custom.

Поле block_scope говорит, где лежит причина блокировки: in_report_scope, если она среди перечисленных находок, и outside_report_scope, если она в той части запроса, которую мы не возвращаем.

Блокировка всегда приходит обычным HTTP-ответом, в том числе при stream: true: решение принимается до открытия потока, поэтому событием внутри стрима она не бывает.