🛠️ Прямой SELECT под ограниченной ролью возвращает ожидаемые строки, под сервисной — ещё одну. Политика RLS существует, но это не доказывает, что она действует для обеих ролей.
Учебная ситуация для PostgreSQL 18 с условной таблицей demo.rls_example: одинаковый запрос в двух сеансах с разными ролями. SELECT sample_id FROM demo.rls_example ORDER BY sample_id; Вымышленные результаты: limited_role → 101, 102; service_role → 101, 102, 103. Запрос не запускался. Такое расхождение ещё не называет причину. Реальные строки, имена и условия политик перед передачей результатов обезличьте.
Первая развилка — фактический контекст запроса. Для диагностики своей таблицы замените схему и имя в двух запросах к каталогам ниже. Выполните их в тех же сеансах и ролях, где обнаружили расхождение: SELECT current_user AS active_role, owner.rolname AS table_owner, c.relrowsecurity AS rls_on, c.relforcerowsecurity AS force_owner, pg_catalog.row_security_active(c.oid) AS rls_active, actor.rolsuper AS is_superuser, actor.rolbypassrls AS bypasses_rls FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_roles AS owner ON owner.oid = c.relowner JOIN pg_catalog.pg_roles AS actor ON actor.rolname = current_user WHERE c.oid = pg_catalog.to_regclass('demo.rls_example'); Пустой ответ этого запроса к pg_class — повод проверить текущую базу, схему и имя объекта, а не заключать, что RLS отключена.
rls_on показывает настройку таблицы; rls_active — действует ли RLS для текущей роли. Если rls_on = true, а rls_active = false, проверьте superuser, BYPASSRLS и права владельца, включая унаследованные при выключенном force_owner. Разные имена active_role и table_owner не исключают обход. FORCE ROW LEVEL SECURITY подчиняет владельца политике, но не отменяет обход superuser и BYPASSRLS.
rls_active = true подтверждает применение RLS; правильность границы доступа проверяется отдельно по применимым политикам: SELECT policyname, roles, cmd, qual FROM pg_catalog.pg_policies WHERE schemaname = 'demo' AND tablename = 'rls_example'; Для прямого SELECT проверьте cmd = SELECT или ALL, roles с учётом PUBLIC и членства, qual как условие USING. Отсутствие применимой политики при действующей RLS закрывает строки по умолчанию — это не причина дополнительных строк. Если применимых политик несколько, один qual не показывает итоговую видимость: важно их сочетание. Подробная логика сочетания выходит за рамки этой диагностики. Сохранённая политика при rls_on = false строки не фильтрует.
Типичная ошибка — менять правило после теста под другой ролью. Полезнее пройти путь от различия результатов через rls_active к возможному обходу и всем применимым политикам. Сохраните порядок проверки роли и политики; такие границы доступа полезно разбирать на практике администрирования PostgreSQL.
🔹🔹🔹🔹