Как это устроено

Приватность по устройству

Изоляция, обеспечиваемая базой данных, шифрование полей ключами по каждому пользователю и честный рассказ о том, что даёт и чего не даёт сквозное шифрование.

Эта страница написана так, чтобы её можно было проверить. Если вы ведёте чужие юридические, миграционные или медицинские дела, изложенные ниже утверждения рано или поздно попросит подтвердить ваш клиент.

Две независимые границы

Тенант
Конечный пользователь
Пространствограница приватности
документыЗащита на уровне строкШифрование на уровне полей
разговорыЗащита на уровне строкШифрование на уровне полей
памятьЗащита на уровне строкШифрование на уровне полей
Защита на уровне строк· обеспечивается Postgres, а не кодом приложенияШифрование на уровне полей· ключ на пользователя, в границах пространства

Две независимые гарантии на одних и тех же строках — ни одна не рассчитывает на то, что держится другая.

Изоляцию обеспечивает база данных, а не код приложения. Защита на уровне строк означает, что запрос, забывший свой фильтр, вернёт ничего, а не чужие строки. От ограничения на уровне приложения до утечки — один забытый WHERE. Здесь гарантия принципиально другого класса, и именно поэтому платформа проводит границу там.

Шифрование от этого не зависит. Даже при доступе к базе содержимое разговоров и документов остаётся шифротекстом.

Конверт

Зашифрованные поля хранятся в фиксированной раскладке:

fmt
1 байт
dek_version
2 байта · big-endian
nonce
12 байт
шифротекст + тег
остальное

Not to scale. На практике основной объём занимает шифротекст — заголовочные поля это считаные байты.

Из этой формы вытекают два следствия.

Ключи можно менять без миграции. Версия путешествует вместе с шифротекстом, поэтому у пользователя может одновременно быть несколько ключей шифрования данных: новые записи используют активный ключ, а при чтении выбирается тот ключ, которым запись была сделана. Ротация превращается в постепенное перешифрование вместо остановки всего мира — а это важно, потому что схему ротации, требующую простоя, обычно так никогда и не применяют.

Шифротекст нельзя перенести. Дополнительные аутентифицируемые данные AEAD привязывают каждое значение к его (tenant, user, space, field). Скопированный в другую строку, другое поле или запись другого тенанта шифротекст не расшифруется, а не выдаст тихо своё содержимое, — поэтому попытка вмешательства на уровне базы не превращается в утечку.

Где живут ключи

Ключ шифрования данных каждого пользователя обёрнут ключом шифрования ключей, спрятанным за абстракцией провайдера ключей. Текущая реализация читает KEK из секретов приложения. Этот шов существует, чтобы KMS, хранилище секретов или собственный ключ тенанта можно было подключить конфигурацией — не меняя ни модель данных, ни вызывающий код.

Скажем точно о нынешнем положении дел: сегодня KEK находится у приложения. Для текущего развёртывания это уместно, но это не то же самое, что ключ под управлением клиента.

Предел любого облачного агента и что с этим делать

К чувствительным разговорам можно добавить сквозной слой: клиент присылает эфемерный публичный ключ ECDH (P-256), сервер выводит сессионный ключ через ECDH и HKDF, и каждая порция потока шифруется AES-GCM и расшифровывается в браузере. Это снижает уязвимость на уровне потоковой передачи — поверх TLS.

Это не zero knowledge, и никакой облачный агент им быть не может. Стоит сказать это прямо, потому что дело в природе задачи, а не в конкретной реализации: чтобы искать по вашей базе знаний, сервер обязан векторизовать и сравнивать ваше содержимое, а чтобы ответить — генерировать по найденным отрывкам. Система, которая не может прочитать материал, не может по нему ни искать, ни отвечать. «База знаний с нулевым разглашением» — противоречие в терминах, и любой поставщик, обещающий и то и другое, описывает одно из двух вольно.

Поэтому честный вопрос не в том, может ли оператор прочитать содержимое, а в том, кто этот оператор.

В нашем облаке мы минимизируем то, что открыто

  • Содержимое шифруется при хранении ключами по каждому пользователю: дамп базы не даёт ничего читаемого.
  • Изоляцию обеспечивает база данных, а не код приложения.
  • В модель уходят только текущее сообщение, найденные под него отрывки и память этого конечного пользователя — никогда база знаний целиком и никогда данные другого пользователя.
  • Сквозной слой защищает поток ответа.

Это заметное сокращение открытой поверхности. Это не то же самое, что наша неспособность прочитать разговор, и мы предпочитаем, чтобы вы услышали это от нас, а не от аудитора вашего клиента.

Там, где требование абсолютно, разворачивайте у себя

Если ваши обязательства означают, что содержимое действительно не может попасть к третьей стороне, ответ не в более сильном заявлении о шифровании — а в развёртывании, где нас нет в цепочке.

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

О том, как рассчитывается, обслуживается и тарифицируется выделенное развёртывание, — на странице тарифа Enterprise.

Что уходит в модель

Ответ на сообщение отправляет модели: само сообщение, найденные под него отрывки и память, извлечённую для этого конечного пользователя. Не базу знаний целиком и никогда не данные другого пользователя — поиск ограничивается пространством ещё до того, как что-либо собирается вместе.

Если вы настраиваете собственного провайдера моделей, содержимое уходит к нему по вашей договорённости с ним, и действуют его условия хранения и обучения. Это ваш договор, а не наш, и его стоит прочитать.

Удаление

Удаление документа убирает и то, что он привнёс в выведенную память, а не оставляет содержимое восстановимым через запись памяти, пережившую свой источник. Сроки хранения и порядок удаления при закрытии аккаунта — в Политике конфиденциальности, а обязательства по обработке данных для бизнес-клиентов — в Соглашении об обработке данных.

Что это даёт на практике

  • Ошибка в запросе не может показать разговоры другого клиента, потому что база данных откажет.
  • Украденный дамп базы не даёт читаемого содержимого.
  • Ключи можно менять в обычном режиме работы, поэтому ротация действительно происходит.
  • Сквозное шифрование — настоящая, но ограниченная опция, и там, где требование абсолютно, ответом служит модель развёртывания, а не более громкое заявление об общей платформе.