Мультиарендность и идемпотентность
AiHummer мультиарендный (multitenant): один gateway может обслуживать много рабочих пространств из одной базы данных, сохраняя их данные раздельно. Это безопасно благодаря двум механизмам — Postgres Row-Level Security (RLS) для изоляции чтения/записи и слою идемпотентности, чтобы ретраи и восстановление хода никогда не дублировали реальный побочный эффект.
Изоляция арендаторов через Row-Level Security
Изоляция обеспечивается на уровне базы данных, а не только в коде приложения.
AiHummer выполняет запросы через ограниченную роль Postgres (aihummer_app),
к которой применены политики RLS, так что сама база отклоняет строки, не
принадлежащие активному арендатору.
RLS подключается опционально. Вы активируете его, передав gateway вторую строку подключения для ограниченной роли:
# gateway.env
# Owner-пул — выполняет миграции и привилегированное обслуживание
AIHUMMER_DATABASE_URL=postgres://aihummer:***@localhost:5432/aihummer?sslmode=disable
# Ограниченная роль — активирует RLS для обычного трафика запросов
AIHUMMER_DB_APP_URL=postgres://aihummer_app:***@localhost:5432/aihummer?sslmode=disable
[!NOTE] Для host-native установок инсталлятор задаёт
AIHUMMER_DB_APP_URLавтоматически, поэтому в стандартном развёртывании RLS включён по умолчанию. Если переменной нет, gateway работает только на owner-пуле, и RLS не активен.
Пер-арендаторное скоупирование
В рамках ограниченной роли каждый запрос ограничивается своим арендатором:
gateway выставляет контекст текущего арендатора для соединения, чтобы политики
RLS разрешались относительно нужного рабочего пространства. Фильтры
WHERE tenant_id = … не расставляются вручную повсюду — политика обеспечивает
это централизованно, а значит пропущенный фильтр не сможет утечь строки другого
арендатора.
Системный / bypass-режим
Часть работы законно межарендаторная — фоновые воркеры, планировщики и задачи обслуживания, действующие на уровне всего инстанса. Они работают в системном / bypass-режиме, чтобы видеть нужное. Bypass зарезервирован для доверенных внутренних воркеров, а не для путей обработки запросов.
[!WARNING] Миграции всегда выполняются на owner-пуле, никогда под ограниченной ролью. Owner-соединение имеет привилегии менять схему и применять политики RLS; ограниченная роль намеренно их не имеет. Держите две строки подключения раздельными и выдавайте роли
aihummer_appтолько необходимое.
Идемпотентные побочные эффекты
Ход (turn) может порождать реальные побочные эффекты: отправку почты, отправку сообщения обратно в канал. Если ход повторяется — из-за временной ошибки или из-за того, что gateway перезапустился посреди хода и восстановление его переигрывает, — эти эффекты не должны произойти дважды. AiHummer гарантирует это двумя взаимодействующими элементами.
Resume-стабильный ключ реестра
Каждый побочный эффект записывается под resume-стабильным ключом реестра: ключ детерминированно выводится из хода, поэтому переигрывание того же хода вычисляет тот же ключ, а не новый. Реестр помнит, какие ключи уже были отработаны.
Барьер побочных эффектов
Прежде чем будет выполнен эффект вроде почты или отправки в канал, он проходит через барьер побочных эффектов, который сверяется с реестром. Если этот ключ уже срабатывал, барьер замыкает накоротко и эффект пропускается; если нет — эффект выполняется, а ключ фиксируется.
запрошен побочный эффект
└─▶ вычислить resume-стабильный ключ реестра
└─▶ барьер: ключ уже зафиксирован?
├─ да ─▶ пропустить (без двойной отправки)
└─ нет ─▶ выполнить эффект ─▶ зафиксировать ключ
В итоге достигается ровно-однократное внешнее поведение, хотя внутренняя доставка работает по принципу не-менее-однократной. Ретраи безопасны по построению — именно это позволяет восстановлению хода (см. Доставку, outbox и восстановление) переиграть прерванный ход без того, чтобы клиент получил то же письмо или тот же ответ дважды.
[!TIP] Поэтому AiHummer может предлагать гарантированную доставку и автоматическое восстановление хода без обычного риска дублей — идемпотентность и есть фундамент, на котором строятся гарантии доставки.
Куда дальше
- Рантайм, ведущий ход: Gateway и turn-движок.
- Как ответы возвращаются ровно один раз: Доставка, outbox и восстановление.