Files
pd-guard/docs/05-limitations.md
T

8.9 KiB
Raw Blame History

Ограничения решения и план развития

Ограничения ниже относятся к поставке, с которой работает жюри: один процесс, правила без моделей, файл config/systems.json, ключ шифрования из application.yml.

Ограничения

Состояние демаскирования не переживает процесс. Соответствия лежат в памяти узла, не дольше 30 минут и не больше заданного объёма символов. Перезапуск, вытеснение и истечение срока делают обратное преобразование невозможным: запрос обрабатывается как новое маскирование, счётчик pdguard.demask.unresolved увеличивается. Общий слой Redis в коде есть и включается pdguard.store.backend=redis, но в текущем compose.yaml его нет: поднят один узел.

Демаскирование разрешено не всем системам и не из браузера. В конфиге оно включено у default и strict. У crm и analytics выключено. Страница http://localhost:8080/ каждый раз создаёт новый payload_id, поэтому с неё можно проверить только маскирование. Чужая система не читает чужое хранилище.

Неизвестное имя системы получает политику default. Отсекаются только явно выключенная система и неверный ключ. Ключ проверяется лишь там, где поле key заполнено; у систем в поставленном файле ключей нет.

Административные методы открыты. GET /admin/config, GET /admin/types и POST /admin/reload не требуют аутентификации. Для стенда хакатона это удобно, для контура с несколькими потребителями — нет.

Ключ шифрования хранилища лежит в конфигурации приложения. AES-GCM включён, но ключ записан в application.yml. Это демонстрационный ключ. В рабочем контуре его нужно задавать снаружи и не хранить в репозитории.

Качество детекции держится на правилах и словарях. Иностранные имена без русских словообразовательных признаков, нестандартные топонимы, составляющие адреса «регион» и «район», а также юридические и банковские реквизиты в нетиповых формулировках без второй и третьей ступеней не размечаются. Третья ступень (LLAIM Legal NER) отдельно закрывает именно эти реквизиты — на датасете реальных логов (NodeLogsDatasetTest) и датасете размещений (PlacementVariantsTest) число подтверждённых утечек заметно ниже именно за счёт неё, регресс без неё был бы больше. Модели в репозиторий не входят: без tools/fetch-ner-model.sh и включённых pdguard.ner.*-engine сервис остаётся на правилах. Сбой любой ступени отключает её до перезапуска, остальные продолжают работать.

Часть типов маскируется только в контексте. PIN, CVV, «голая» дата, место рождения, страна, банковские реквизиты организации, доход и слово о биометрии сами по себе не закрываются. Биометрия в тексте — это упоминание, а не шаблон из базы. Режим MASK по задумке оставляет края длинных номеров и инициалы ФИО; полностью закрывает режим STRICT.

Синтетика покрывает не все типы. Где своей подстановки нет, SYNTHETIC ставит токен вида [TYPE_1].

Журнал не является аудитом значений. Пишутся идентификатор, длина и счётчики типов. Восстановить по журналу, что именно скрыто, нельзя — и отдельного аудита решений оператора тоже нет.

Ответ модели — внешняя зависимость. Пока pdguard.llm.url пуст, POST /proxy отвечает заглушкой. Ошибка живой модели тоже подменяется заглушкой, чтобы сбой модели не раскрывал исходный текст. Контракт /process от модели не зависит.

Нагрузка измерена на коротких текстах и на правилах. Прогон k6 использует систему crm и тексты в одну-две строки. Длинный документ и включённая модель этот профиль не описывают: модель вызывается точечно, но один вызов BERT — это уже десятки миллисекунд.

Внутренняя ошибка выглядит как успешный ответ. HTTP-код остаётся 200, тело — [обработка недоступна]. Так исходный текст не утекает и автоматический прогон не останавливается на серии ошибок. Отличить сбой от маски можно по этой фиксированной строке и по метрике pdguard_requests_rejected_total{reason="internal_error"}.

План развития после хакатона

Контур и секреты. Вынести ключ шифрования и секреты систем в хранилище секретов. Закрыть /admin аутентификацией. Неизвестную систему отклонять, а не сажать на default. Включить Redis в поставку compose как общий слой соответствий и прогнать демаскирование через балансировщик.

Детекция. Поставлять модели второй ступени отдельным артефактом со проверкой целостности и измеренным p95 на включённой ступени. Добавить типы документов, которых не хватает по отраслевому перечню, отдельными правилами в реестре — ядро и политики с "*" подхватят их без миграции. Расширить внешние словари (известные люди, денилист улиц) как файлы, которые перечитываются так же, как config/systems.json.

Качество и нагрузка. Закрепить в CI прогон размеченных наборов (precision/recall по типам) и сценарий k6 с порогом p95 ≤ 0,5 с при 1000 запросах/с на полном перечне типов, а не только на политике crm. Замерить длинные документы отдельно от коротких обращений.

Наблюдаемость для эксплуатации. Журнал решений без значений персональных данных в централизованный сбор. Алерты на рост demask_unresolved, на отказы по перегрузке и на выключение второй ступени. Срок хранения соответствий и потолок объёма сделать разными для систем.

Интерфейс политики. Страница проверки сейчас только маскирует. Следующий шаг — показать демаскирование тем же payload_id и дать править перечень типов и режим без ручного JSON, с тем же файлом systems.json под капотом.