AiHummer доки
v1.0.x
RU EN

Row-Level Security

v1.0.x · обновлено 2026-06-26

AiHummer многоарендный, и его самая прочная граница изоляции находится в самой базе данных: PostgreSQL Row-Level Security (RLS). При включённом RLS база данных — а не только код приложения — гарантирует, что запрос видит только строки, принадлежащие текущему арендатору.

Зачем RLS

Фильтрация на уровне приложения (WHERE tenant_id = ...) необходима, но хрупка: одно забытое условие может «утечь» данные между арендаторами. RLS переносит гарантию в PostgreSQL, так что даже нефильтрованный запрос вернёт только строки текущего арендатора. Это слой эшелонированной защиты под собственным скоупингом приложения. Полную модель multitenancy — и как она сочетается с идемпотентными побочными эффектами — см. в Multitenancy и идемпотентность.

Ограниченная роль (опционально)

RLS включается опционально — передачей gateway второго подключения к базе, которое использует ограниченную роль вместо владельца:

# /home/.aihummer/etc/gateway.env
# Пул владельца — выполняет миграции, используется для system/bypass операций
AIHUMMER_DATABASE_URL=postgres://owner:...@localhost/aihummer

# Ограниченный пул приложения — действуют политики RLS (роль aihummer_app)
AIHUMMER_DB_APP_URL=postgres://aihummer_app:...@localhost/aihummer

Роль aihummer_app не является владельцем таблиц, поэтому PostgreSQL применяет к ней политики RLS. Запросы приложения идут через этот ограниченный пул. Для host-native установок инсталлятор подключает AIHUMMER_DB_APP_URL автоматически.

[!NOTE] Без AIHUMMER_DB_APP_URL gateway использует пул владельца для всего, и RLS фактически не применяется. Задайте ограниченный пул, чтобы включить изоляцию на уровне базы данных.

Скоупинг на арендатора

Внутри запроса приложение устанавливает текущего арендатора на подключении до выполнения запросов, скоупленных по арендатору — концептуально db.WithTenant. После скоупинга политики RLS на ограниченной роли ограничивают каждое чтение и запись строками этого арендатора. Скоуп привязан к единице работы, поэтому он не утекает между параллельными запросами.

запрос ─▶ определить арендатора ─▶ db.WithTenant(арендатор) ─▶ запросы видят только его

Режим system / bypass для воркеров

Часть работы законно кросс-арендна или не привязана к арендатору — фоновые воркеры, планировщики, outbox и подобная механика. Для них gateway использует режим system (bypass), который работает на пуле владельца, вне политик RLS на арендатора, чтобы инфраструктурные задачи могли работать со всем набором данных.

[!WARNING] Режим bypass — только для доверенных внутренних воркеров. Кодовые пути обработки запросов, действующие от имени пользователя, всегда должны идти через ограниченный, скоупленный по арендатору пул — никогда через путь bypass.

Миграции выполняются на пуле владельца

Изменения схемы требуют привилегий, которых у ограниченной роли нет, поэтому миграции всегда выполняются на пуле владельца (AIHUMMER_DATABASE_URL), под advisory-lock, при старте. Ограниченная роль aihummer_app используется только для обычного трафика приложения. Это держит разделение привилегий чистым: операции изменения схемы — у владельца; доступ к данным арендаторов — у ограниченной роли с применением RLS.

Куда дальше