Архитектура
flowchart LR
Owner["Владелец"] -->|POST /api/bots| Backend
Backend -->|"Bot user (is_bot=true)<br/>+ BotToken (hash)"| DB[(Хранилище)]
Owner -->|invite в Space| Backend
Backend -->|BotMembership<br/>scopes + channels| DB
User["Пользователь"] -->|"/ping (slash-команда)"| Backend
Backend -->|"emit command.invoked<br/>(адресно боту)"| Dispatcher[Webhook<br/>dispatcher]
Dispatcher -->|HMAC sign + POST| BotServer["Сервер бота"]
BotServer -->|"Authorization: Bot<br/>POST /api/bot/.../messages"| Backend
Backend -->|"voice access token"| Voice[Reason Space Voice]
BotServer -->|publish audio| Voice
Сущности
| Entity | Описание |
|---|---|
| User | Любой пользователь, в том числе бот (is_bot=true) |
| Bot | Метаданные бота: owner, description, state, visibility |
| BotToken | Static API-token. HMAC-SHA256 keyed-MAC. Один активный per bot. |
| BotMembership | Per-space scope-list + allowed_channels |
| BotWebhook | Подписка на events: URL + space_filter. Секрет хранится hashed в БД; plaintext для HMAC-подписи держится в памяти процесса и теряется при рестарте (шифрование at-rest — TODO Phase 4.5) |
| BotAuditLogEntry | Каждое mutate-action. 90-day retention. |
Два API-канала
Bot-facing API (/api/bot/*)
Что бот может делать: отправить сообщение, добавить реакцию, зайти в
voice. Авторизация — Authorization: Bot <token> (static API-token).
Webhook events
Что бот получает: каждое релевантное событие в Space (command.invoked, voice.joined, voice.left…). Платформа HMAC-подписывает каждое delivery ключом, выданным при создании webhook'а.
Privacy boundaries
Запрещено платформой (не настраивается scope'ом):
- Бот не модератор voice-комнат (no kick / mute / record).
- Бот не получает аудио других участников. Гарантия на уровне сервера.
- Бот не читает E2E-encrypted сообщения. Текст бот получает только как
структурированные
optionsslash-команды через событиеcommand.invoked— по явному opt-in пользователя, ≤1024 байта, не попадают в ленту чата. - Бот не видит DM других пользователей.
- Бот виден только в
allowed_channels.
Подробнее: Privacy.
Lifecycle бота
stateDiagram-v2
[*] --> draft: POST /api/bots
draft --> active: ready to invite
active --> suspended: owner suspend
suspended --> active: owner resume
active --> revoked: leak detected
revoked --> [*]: DELETE /api/bots/{id}
active --> deleted: owner delete
deleted --> [*]
При revoked все токены становятся невалидны мгновенно. При suspended —
тоже невалидны, но можно вернуть. См. Lifecycle.