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 tokensHMAC-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/16 | RFC1918 private |
127.0.0.0/8, ::1 | loopback |
169.254.0.0/16 | link-local (AWS metadata) |
fc00::/7 | IPv6 ULA |
Каждое delivery resolve'ит DNS перед connection — нельзя обмануть DNS-rebinding'ом.
Если токен утёк
Автоматического отзыва токенов по GitHub Secret Scanning пока нет — платформа не получает уведомлений об утечке. Если токен попал в публичный репозиторий, логи или куда-то ещё, отвечает за реакцию владелец бота.
При подозрении на утечку немедленно ротируйте токен:
POST /api/bots/{bot_user_id}/tokens/rotate
Ротация выдаёт новый bot_<...> токен и инвалидирует старый. Старый токен
после этого не пройдёт аутентификацию.
GDPR / Right to be forgotten
Когда пользователь запрашивает удаление:
- Юзер удаляется из
space_members - Бот не получает webhook о выходе пользователя в этом сценарии.
Событие
member.leftдоставляется боту только когда сам бот кикнул участника (scopemoderation.kick); при обычном выходе, админ-removal или удалении аккаунта webhookmember.leftботу не отправляется. Поэтому для GDPR-очистки нельзя полагаться на этот webhook — отслеживайте актуальный состав участников через REST (GET /api/bot/spaces/{space_id}/members) или очищайте локальные ссылки на user_id по TTL - По политике хранения записи 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.
options команд + user_ids — OK; content (encrypted blob) — нет.
GDPR compliance: не хранить вечно.
Для production-ботов.