Перейти к основному содержимому

Privacy & Security

Гарантии платформы

Нельзя обойти ни одним scope'ом — это константы платформы:

Бот не модератор voice-комнаты. В выпущенном voice access-токене прав модератора нет. Бот не может kick, mute или начать запись.

Бот не получает аудио других участников. Поведение гарантировано на уровне сервера. Запрос подписки на чужие audio-потоки отклоняется независимо от настроек клиента.

Бот не читает E2E-encrypted chat. Контент сообщений шифруется на клиенте, ключи только у участников Space'а. Единственный plaintext-текст, который получает бот, — это структурированные options slash-команды через событие command.invoked: они приходят только по явному opt-in пользователя, ограничены схемой зарегистрированной команды, лимитированы 1024 байтами и не попадают в чат/ленту/модерацию. См. Команды.

Бот не видит DM. Direct messages физически изолированы от bot-visible data.

Бот видит только allowed_channels. При invite владелец выбирает каналы. Любой запрос за пределы — 403 + audit log.

Что аудитится

Каждое mutate-action бота → запись в audit log:

bot_user_id | space_id | action | target_id | payload_summary
e8e3... | 019b... | message.send | <msg> | {"channel_id": "...", "len": 42}
e8e3... | 019b... | voice.join | <ch> | {"publish_audio": true}
e8e3... | 019b... | scope_denied | <ch> | {"detail": "missing scope: messages.send"}

Retention 90 дней. Audit log доступен только владельцу бота через UI (Bots → Audit log). Третьи стороны не имеют к нему доступа.

payload_summary — сжатый summary без полного контента. Никаких полных сообщений не сохраняется.

Шифрование at-rest

Bot static tokens

HMAC-SHA256 keyed-MAC с master key. Fast verify (~1µs), нельзя восстановить plaintext без master ключа.

Webhook secrets

В БД хранится только hash секрета. Plaintext для HMAC-подписи держится в памяти процесса и не переживает рестарт сервера: после рестарта/редеплоя API доставки временно идут без заголовка X-Reasonspace-Signature (unsigned), пока секрет не будет задан заново (пересоздание webhook'а через DELETE + POST). Обрабатывайте отсутствие X-Reasonspace-Signature как отдельный случай.

У ботов нет OAuth: аутентификация бота — исключительно статический Bot-токен (Authorization: Bot <token>). Никаких client secrets, refresh tokens или access tokens для ботов не существует.

SSRF guard для webhook URLs

DNS-pin + private-IP blocker:

Запрещённые subnet'ыЗащита от
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16RFC1918 private
127.0.0.0/8, ::1loopback
169.254.0.0/16link-local (AWS metadata)
fc00::/7IPv6 ULA

Каждое delivery resolve'ит DNS перед connection — нельзя обмануть DNS-rebinding'ом.

Если токен утёк

Автоматического отзыва токенов по GitHub Secret Scanning пока нет — платформа не получает уведомлений об утечке. Если токен попал в публичный репозиторий, логи или куда-то ещё, отвечает за реакцию владелец бота.

При подозрении на утечку немедленно ротируйте токен:

POST /api/bots/{bot_user_id}/tokens/rotate

Ротация выдаёт новый bot_<...> токен и инвалидирует старый. Старый токен после этого не пройдёт аутентификацию.

GDPR / Right to be forgotten

Когда пользователь запрашивает удаление:

  1. Юзер удаляется из space_members
  2. Бот не получает webhook о выходе пользователя в этом сценарии. Событие member.left доставляется боту только когда сам бот кикнул участника (scope moderation.kick); при обычном выходе, админ-removal или удалении аккаунта webhook member.left боту не отправляется. Поэтому для GDPR-очистки нельзя полагаться на этот webhook — отслеживайте актуальный состав участников через REST (GET /api/bot/spaces/{space_id}/members) или очищайте локальные ссылки на user_id по TTL
  3. По политике хранения записи audit-лога живут 90 дней (поле target_user_id — nullable). Очистка/анонимизация по истечении срока — на стороне ретеншен-политики; отдельного автоматического обнуления target_user_id в текущей реализации нет

Webhook payload'ы на стороне бота — это его собственные logs, платформа их не видит и не контролирует. Разработчик бота отвечает за их GDPR-compliance.

Что НЕ доступно боту

Эти данные не передаются боту ни через один API, ни через webhook:

  • Email пользователя
  • IP-адрес
  • Реальное имя и глобальный display_name (боту доступен только space-nickname через members.read)
  • Связки с Telegram / другими identity
  • Список других Space'ов пользователя

История сообщений канала боту доступна через GET /api/bot/spaces/{space_id}/channels/{channel_id}/messages (scope messages.read) — включая сообщения до его invite (временно́го гейта нет). Но content пользовательских сообщений приходит E2E-зашифрованным: без ключей бот его не расшифрует, доступны лишь метаданные (UUID-авторы, время, reply-структура) и шифртекст.

Чек-лист разработчика

Не хранить токены в коде

Только env-переменные. .env в .gitignore.

Не логировать payload'ы plain

options команд + user_ids — OK; content (encrypted blob) — нет.

TTL на user_id кэшах

GDPR compliance: не хранить вечно.

HTTPS-only webhook URLs

Для production-ботов.