Глава 7 — Реализация контроля доступа
Седьмой пост поглавного разбора LLM Primer III: Enhancing Enterprise AI with RAG. Модели прав, сделанные для реляционных баз и файловых систем, не вполне подходят для поиска. Единица доступа теперь не строка и не файл, а эмбеддинг — а эмбеддинг способен сливать оригинал через сходство, даже когда сам документ закрыт.
Почему существует эта глава
Глава 6 произвела модель угроз. Самый важный контроль, который она подразумевает — и который большинство ранних продакшен-систем делает неверно — это контроль доступа на слое поиска, чтобы LLM никогда не видела контент, на который у пользователя нет прав. Наивная альтернатива «отфильтруем во время генерации» строит confused deputy: модель уже прочла закрытые документы и сольёт их содержание через перефразирование.
Эта глава проходит по четырём механизмам, складывающимся в рабочий стек контроля доступа: документ-уровневые ACL как фундамент, RBAC, интегрированный с уже существующими метками чувствительности предприятия, ReBAC под реальность корпоративного знания, имеющую форму отношений, и дисциплина pre-filter против post-filter, работающая под всеми ними.
7.1 Документ-уровневые ACL и фильтрация по метаданным
Каждый чанк знает, кому разрешено его видеть. Реализация проста в описании; режимы отказа достаточно тонкие, чтобы почти каждая ранняя продакшен-система ошиблась хотя бы раз. Три детали важнее всего. Гранулярность: у длинного отчёта может быть публичное резюме и конфиденциальное приложение, и единственный документ-уровневый ACL, скопированный единообразно вниз на чанки, либо переоткрывает приложение, либо закрывает резюме. Паттерн, масштабирующийся хорошо, — носить секционные права через парсинг с учётом макета.
Свежесть: права меняются. Запекать ACL в чанк во время индексации и больше не переоценивать — значит получить систему, которая лжёт. Храните стабильный идентификатор в метаданных чанка и разрешайте живой ACL против исходной системы во время запроса, за коротко-TTL кешем. Негативное пространство: если ответ живёт в закрытом документе, система не должна галлюцинировать или уверенно говорить «я не знаю» — она должна сказать «по этой теме есть материал, который вы не вправе видеть». Это требует либо второго нефильтрованного вызова, либо векторной базы, различающей «нет совпадения» и «совпало, но отфильтровано», — и большинство реализаций уклоняются.
7.2 RBAC и метки чувствительности Microsoft Purview
RBAC сжимает пространство прав — вместо миллионов рёбер user-to-document политика сводится к нескольким сотням рёбер role-to-classification, что и аудитуемо, и поддерживаемо. Чисто ложится на RAG, когда предприятие уже на нём живёт. В средах Microsoft это означает группы Entra ID и метки чувствительности Purview: Public, General, Confidential, Highly Confidential с возможными подметками. Метка едет с документом; парсер читает её во время индексации и пишет стабильный идентификатор метки в метаданные чанка.
Интеграция проста, дрейф — нет. Если индексатор работает как сервисная учётка, способная расшифровать всё, а система поиска применяет role-based фильтр поверх индекса, то документ, перемаркированный с General на Confidential, не получит перемаркировку уже индексированных чанков, пока индексатор не заметит изменение. Системы, делающие это правильно, гоняют непрерывную сверку против источника. Системы, делающие это неправильно, обнаруживают дрейф во время аудита, и находка серьёзная.
7.3 ReBAC с Zanzibar и SpiceDB
RBAC не способен выразить «любой в продажах, кто также назначен на сделку Acme Corp». Это требует рассуждения об отношении между пользователем и ресурсом, а не только о роли. Relationship-based access control, формализованный в статье Zanzibar в Google и доступный в open-source как SpiceDB и OpenFGA, хранит граф: «Алиса — член Engineering», «Engineering — viewer папки Specs», «Spec-101 — в Specs». Проверки прав становятся обходами графа.
Паттерн интеграции с RAG чист. SpiceDB получает вопрос: какие документы может видеть этот пользователь? — и возвращает список идентификаторов; поисковая система передаёт его как фильтр метаданных в векторный поиск. Zookies Zanzibar позволяют поисковому вызову требовать консистентности не старше только что выданного доступа: пользователь, добавленный в проект в 10:00 и задавший вопрос в 10:01, увидит новые документы. Операционная цена — SpiceDB становится критической зависимостью на пути запроса, требующей HA и агрессивного short-TTL кеширования списков документов по пользователю. Зрелые системы часто используют и RBAC, и ReBAC: RBAC для широкой политики чувствительности, ReBAC для точной политики отношений, объединяемых как пересечение разрешённых множеств.
7.4 Pre-filter, post-filter и дисциплина под обоими
Pre-filtering применяет предикат авторизации до векторного поиска: индекс сначала ограничивает множество кандидатов, затем считает сходство по ограничению. Концептуально чисто и более безопасный дефолт, но производительность зависит от структуры индекса. HNSW с очень селективным фильтром способен резко деградировать, поскольку обход графа идёт через много несовпадающих узлов; варианты filterable-HNSW в Weaviate и Qdrant и per-tenant namespaces в Pinecone и Milvus смягчают, но не устраняют цену.
Post-filtering меняет порядок. Полная скорость HNSW, более слабая безопасность: утечка через top-K, утечка через тайминги и утечка корректности, когда весь top-K оказался отфильтрован. Прагматичный продакшен-ответ — наслоить оба: pre-filter по самому грубому и быстрому предикату (тенант, широкая роль), post-filter по дорогим точным предикатам (списки SpiceDB, метки Purview) и выбирать с запасом — top-50 вместо top-10, чтобы post-filter оставлял полное ранжированное множество. Ещё два места протекают: шаблон промпта, цитирующий название конфиденциального документа, и кеш ответов, ключенный только по строке запроса. Оба должны быть частью поверхности авторизации.
Что подготавливает глава 7
Контроль доступа отвечает на кто может видеть что. Он предполагает, что есть что закрывать. И не спрашивает, должен ли чанк быть заэмбежден в той форме, в которой это сделано — должны ли имена клиентов, номера соцстрахования, проприетарные пути кода сидеть в векторном хранилище вовсе, ожидая правильной авторизации, чтобы всплыть. Это вопрос анонимизации, и он — тема следующей главы.
Дальше — Глава 8: Анонимизация данных в RAG-пайплайне. До генерации против после генерации, маскирование против синтетической замены против дифференциальной приватности и компромисс полезность–приватность, через который проходит каждый выбор.