Назад в блог
RAG Systems

Права доступа в RAG: как не показать сотруднику чужие документы

Authorization должна ограничить retrieval до того, как модель получает context

Trusted identity, policy-derived scope, eligible evidence, revocation и fail-closed routes

Авторский ACL-RAG-8 workflow с permission-aware pseudocode и acceptance gates
права доступа в RAG, permissions RAG, контроль доступа, RAG security, document access и ACL-RAG-8
ТемаPermission-aware evidence routing
ФокусACL-RAG-8
СтатусPUBLISHED / 2026-08-30
Две изолированные зоны документов проходят через permission gateway к проверяемому RAG-ответу
Две изолированные зоны документов проходят через permission gateway к проверяемому RAG-ответу
TERMINAL_PREVIEW.LOG
$ enforce rag-access --contract ACL-RAG-8
> resolve: session / subject / tenant / entitlements
> evaluate: purpose / collection / lifecycle / policy
> retrieve: eligible passages only
> verify: isolation / citation / revocation / trace
> route: answer / deny / clarification / review
Разбор

Права доступа в RAG — это не инструкция в промпте «не раскрывай конфиденциальное». Модель видит только переданный ей context, поэтому границу нужно применять до того, как candidates попадут в retrieval, reranking и prompt. Если сотрудник может найти документ другого tenant, команды или lifecycle, вежливый финальный ответ уже не исправит утечку.

Материал отвечает на технический запрос «права доступа в RAG»: identity, policy, document permissions, retrieval и эксплуатационные проверки. Более широкую задачу проектирования продукта покрывает страница RAG-систем. Для архитектурного разбора команда может начать с AI engineering brief; статья поддерживает эту landing page техническими критериями, а не подменяет её.

Начните с authorization decision, а не с similarity search

Каждый запрос должен приходить в retrieval с trusted subject, сформированным на сервере. Полезный request record содержит tenant или организационную границу, immutable user ID, актуальные роли или entitlements, purpose при необходимости, session и версию policy. Название роли, document ID и фильтры из браузера — это вход для проверки, а не authority, которому можно доверять.

Оформите решение отдельным контрактом:

json
{
  "subject": { "tenantId": "north", "userId": "u_42", "roles": ["support"] },
  "resourceScope": { "collections": ["help-center"], "lifecycle": ["current"] },
  "policyVersion": "access-2026-08",
  "decision": "allow-retrieve"
}

Identity service, application authorization layer и retrieval service могут быть разными компонентами, но должны одинаково понимать этот record. Не превращайте роль в неограниченный vector-store filter в browser code. Не заменяйте отсутствующий scope на более широкий corpus. Неполный или непроверяемый scope должен вести к controlled denial, уточнению или human route.

ACL-RAG-8: authorization-first архитектура retrieval

ACL-RAG-8 — это engineering sketch, который удерживает границу от запроса до ответа:

text
REQUEST + authenticated session
  -> resolve server-side subject, tenant и active entitlements
  -> evaluate policy для retrieval purpose и collection
  -> construct trusted retrieval scope
  -> filter candidates по tenant, ACL, lifecycle и source version
  -> rank только eligible set
  -> select citable evidence и verify claim coverage
  -> answer | deny | clarification | review

Фильтрация после top-k retrieval небезопасна по умолчанию: неразрешённый контент уже может повлиять на traces, caches, reranking inputs или observability. Предпочтителен engine-level filter, полученный из trusted scope. Если storage не выражает существенный entitlement точно, поставьте deterministic policy gate до него или сузьте архитектуру corpus. Similarity score — не permission.

Не менее важен ingestion. Дайте каждому source и passage стабильные source ID, version, tenant, collection, access attributes, lifecycle и human-openable locator. Chunk наследует доступ от authoritative document record; после удаления пользователя или архивации он не должен хранить устаревшее разрешение. Почему эти поля должны ограничивать retrieval, а не украшать его, разбирает статья о метаданных и фильтрах в RAG.

Представляйте permissions как связи данных, а не только role labels

RBAC часто полезен как первый слой, но production policy обычно сочетает несколько отношений:

СвязьПримерСледствие для retrieval
TenantДва клиента используют один indexCandidate должен совпасть с trusted tenant boundary
RoleSupport читает approved help articlesРоль резолвится в явную collection или action
Resource ACLDesign note доступна только project teamCandidate сверяется с membership документа или collection
LifecycleЧерновик policy не customer-facingSuperseded, draft и quarantined versions неeligible
PurposePrivileged export требует отдельного approvalPurpose проверяется на сервере, не выводится из prompt

Не сводите все правила к долгоживущим vectors user IDs, если membership часто меняется. Сохраняйте source of truth членства и процесс reconciliation, который отзывает доступ или переиндексирует affected passages. Но и грубая роль не защищает document-level exception. Конкретная модель зависит от размера corpus, частоты изменений и стоимости ошибки; инвариант один: semantic similarity не делает candidate eligible.

Failure modes, которые нужно проверить до запуска

Пропущен cross-tenant filter. Разработчик тестирует один workspace и забывает tenant predicate в новом retrieval path. Нужны обязательный trusted-scope constructor, integration tests с двумя tenant и fail-closed default, если tenant отсутствует.

Stale entitlement после отзыва. Пользователь теряет доступ, но cache или background index держит старый ACL. Сохраняйте policy и membership versions, задайте bounded cache lifetime, reconcile changed documents и тестируйте реальный revoke с повторным запросом.

Authorization после retrieval. UI скрывает citation после ranking, хотя модель уже получила passage. Перенесите enforcement вверх: неразрешённые passages не должны появиться в results, reranking input, prompt или unredacted diagnostics.

Client-controlled scope. Запрос принимает department=finance из браузера как effective scope. Сервер должен resolve department и entitlements из authenticated session, а optional filter — только сузить уже доверенную границу.

Fallback расширяет corpus. Empty result запускает «полезный» поиск по всем документам. No-answer безопаснее. Любой fallback должен быть отдельно разрешён policy и протестирован.

Логи становятся вторичной утечкой. Retrieval traces способны сохранить title, snippet или query text. Минимизируйте payload, применяйте access control к observability и отдельно проверяйте operator roles.

Соберите authorization acceptance set

Тестовый набор доступа строится на реальных policy relationships, но с безвредными fixture documents, которые легко различить. Покройте allowed retrieval, denied retrieval, document-level exception, lifecycle change, membership removal, stale-cache simulation, empty result и пользователя с двумя разрешёнными scope. Запускайте эквивалентные prompts с разной identity: expected result меняется из-за policy, а не из-за формулировки.

GateЧто сохранить как evidence
Trusted identityserver-derived subject, session и policy version
Eligibilitytenant, ACL, lifecycle и source version до ranking
Isolationdenied source отсутствует в candidate, context, citation и trace
Revocationchanged membership наблюдается в документированной recovery boundary
Fallbackempty result не расширяет доступный corpus молча
Operationsназначен owner policy changes, incidents, audit review и rollback

Измеряйте allow и deny outcomes отдельно. Высокий answer-quality score не доказывает isolation. Для sensitive cases сверяйте threat model и audit requirements с владельцем данных: это архитектурный материал, а не юридическая или compliance-консультация.

Bounded production rollout

Начните с одного workflow, малого набора collections и нескольких named roles. Зафиксируйте policy, ingestion и index configurations для теста. Добавьте kill switch или route, который возвращает bounded no-answer, пока расследуется policy incident. До расширения убедитесь, что revoke, re-index, cache invalidation и trace redaction проходят тем же production-like путём, который обслуживает реальные запросы.

ts
const scope = await resolveTrustedScope(serverSession, request.purpose);
if (!scope.isComplete) return { route: "deny-or-clarify" };

const candidates = await retrieve({
  query: request.query,
  tenantId: scope.tenantId,
  allowedCollections: scope.collections,
  allowedSubjects: scope.entitlements,
  lifecycle: "current",
});

if (candidates.some((item) => !policyAllows(item, scope))) throw new Error("policy breach");
return composeCitedAnswer(selectEvidence(candidates));

Это control sketch, а не универсальная реализация. Содержательные production criteria — server-trusted identity, deterministic eligibility до model context, наблюдаемый revoke и безопасный refusal path. Именно эти вопросы стоит принести на RAG architecture review до расширения доступа внутреннего ассистента.

CODE_BLOCK.TXT
require(scope.isServerTrusted && scope.tenantId);
require(policy.allows(request.purpose, scope));
require(candidate.tenantId === scope.tenantId);
require(candidate.lifecycle === "current");
require(testSet.allowed && testSet.denied && testSet.revoked);
require(testSet.emptyResult && testSet.traceRedaction);

if (!scope.isComplete) route = "deny-or-clarify";
if (!evidence.isPermitted) route = "fail-closed";