diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6bccc..8ca69e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,25 +96,45 @@ - Критерий приёмки: после пилота на одной команде в журнале есть не менее 5 реальных записей, каждая с категорией данных и отметкой обезличивания; повторяющаяся операция закрывается одной строкой, без ручного заполнения таблицы каждый раз. - Причина: в папке «AI безопасность» журнал присутствует только как пустая форма Регламента. Пустая форма — не контроль. -### 4. Принуждение на исходящем запросе — механизм есть, не хватает решения +### 4. Перехват на исходящем запросе: маска + журнал, роли по типам документов Проверено 05.11.2026 по установленной сборке: точка перехвата в Hermes существует и врезана в путь запроса. - Плагин регистрирует middleware: `ctx.register_middleware("llm_request", fn)` — `hermes_cli/plugins.py:939`. - Применяется перед вызовом провайдера: `agent/turn_api_request.py:156` → `apply_llm_request_middleware(...)`, и `api_kwargs` заменяются тем, что вернул плагин (`hermes_cli/middleware.py:88`). - Middleware видит полный `request`, включая `messages`/`input`, и может переписать их или прервать вызов исключением. -- Парный механизм `llm_execution` оборачивает сам вызов провайдера — там же делается обратная подстановка масок в ответ. +- Парные точки: `tool_request` (аргументы инструмента до выполнения) и `llm_execution` (обёртка самого вызова провайдера). -Значит «перехвата нет» — это про отсутствие реализации, а не про отсутствие возможности. Реально мешают четыре решения, а не код: +**Решение Олега 05.11.2026: режим — маскировать и логировать.** Блокировка — только там, где маскирование бессмысленно. Причина: шаблоны ПДн дают ложные срабатывания на техническом тексте (номера СП и ГОСТ, ИНН поставщика в спецификации, кадастровые в выписке), а жёсткая блокировка валит нормальную работу и толкает её на личный телефон. -1. **Режим по умолчанию.** Жёсткая блокировка толкает работу на личный телефон (об этом прямо предупреждает отраслевой разбор). Нужен режим «маскировать + писать в журнал», блокировка — только для красной категории. -2. **Обратная подстановка.** Маска на входе без демаскировки ответа делает ответ бесполезным: модель вернёт `[РОЛ_01]`. Нужны две точки — `llm_request` и `llm_execution`. -3. **Ложные срабатывания.** Шаблоны ловят номера СП и ГОСТ, ИНН поставщика, кадастровые в спецификации. Нужен период «warn»: только журнал, правила настраиваются на реальном потоке 20–30 запросов. -4. **Правовая рамка.** Middleware обрабатывает ПДн внутри агента → агент становится средством обработки. Карта соответствий хранится вне модели, журнал обязателен. +**Категория — не по шаблону, а по типу документа и роли.** Классификатор угадывает и ошибается; поэтому тип документа определяется до чтения, а подтверждает человек одним вопросом, и ответ живёт в метке сессии. -Чего не закроет и перехват: картинки (vision), вложения, и путь «человек скопировал в браузер мимо агента» — это только шлюз или DLP на периметре. +Три точки в одном плагине: -- Критерий приёмки: на контрольном запросе с ФИО, ИНН и адресом в модель уходит маска, в журнале появляется строка, ответ возвращается с реальными значениями; на 20 запросах без ПДн — ноль блокировок и ноль ложных масок. +| Точка | Что делает | +|---|---| +| `tool_request` (`read_file`, DOCX/PDF-парсер, OCR) | определяет тип документа по имени файла, титулу и штампу; сверяет с ролью пользователя; ставит метку категории в сессии; при запрете — отказ **до** чтения файла, содержимое в модель не попадает | +| `llm_request` | маскирует по правилам категории из метки; пишет строку в журнал | +| `llm_execution` | возвращает реальные значения в ответе (демаскировка) | + +Политика — файл в профиле (`policy.yaml`), правится без пересборки: + +| Категория | Кому | Что входит | Режим | +|---|---|---|---| +| 🟢 зелёный | всем | открытые нормативы, методики, обезличенные тексты | без маски | +| 🟡 жёлтый | всем | ТЗ, реестры замечаний, переписка, локальные сметы, ВОР | маска + журнал | +| 🔴 красный | только роль «договорной пул» (несколько человек) | договоры, сводные сметы, акты, ИД, кадры, финансы | остальным — отказ с подсказкой, к кому идти | + +Маскировать красное и отправлять нельзя: у договора маска убивает предмет — стороны, суммы, особые условия. Поэтому для красного единственный корректный ответ — не пускать. + +- Критерий приёмки: + 1. Сотрудник без роли просит проверить договор → отказ до чтения, файл не открывается. + 2. ТЗ у любого сотрудника → уходит маской, в журнале строка, ответ приходит с реальными значениями. + 3. 20 запросов без ПДн → ни одной маски и ни одной блокировки. + 4. В журнале: пользователь, тип документа, категория, сколько замен, модель, время. +- Остаточные риски, фиксируем честно: картинки и вложения не маскируются; PDF-сканы без текстового слоя требуют OCR до маски; путь «человек скопировал в браузер мимо агента» закрывается только шлюзом или DLP на периметре. + +Порядок работ: сначала `tool_request` + политика + журнал в режиме «только запись» (ничего не маскируем, смотрим поток), затем включаем маску на жёлтом, и только после настройки правил — демаскировку ответа. ### 5. Состав из «Mastermind — требования к следующей сборке»