Cluster · разработчикам
Профиль и вход
Профиль содержит логин, почту и пароль Cluster. Telegram подключается отдельно. Его можно заменить, сохранив юзербота, модули и данные.
Начнём с формата профиля, который получает сайт:
from typing import Literal, TypedDict
class Profile(TypedDict):
id: str
login: str
email: str
state: Literal["pending", "active", "deleting", "deleted"]
unit: str
telegram: int | NoneЭто описание полей ответа GET /api/auth/profile, импортировать Profile из Cluster не нужно. Пароль, его хеш, секрет TOTP и Telegram-сессия в ответ не входят.
id сохраняется на всё время существования профиля. unit указывает на собственный юзербот. telegram содержит привязанный Telegram ID либо None. Дополнительный овнер использует свой профиль, даже когда управляет чужим юзерботом.
Регистрация
Логин принимает 3-32 латинских буквы, цифры и подчёркивание. Регистр не учитывается. Пароль принимает 12-256 символов, почта приводится к нижнему регистру.
После регистрации профиль ожидает подтверждения (pending), юзербот остановлен. Код из письма подтверждает почту и активирует профиль (active). До подтверждения войти нельзя. При занятом логине или адресе сервер также отвечает {"accepted": true}, не раскрывая наличие чужого профиля.
Почтовый код действует 30 минут. У него одно назначение: verify для регистрации, reset для пароля или email для смены почты. Код применяется один раз. В базе хранится его хеш, исходное значение остаётся в зашифрованной очереди только до отправки или истечения срока.
Пароль хранится как Argon2id: 64 MiB памяти, три прохода, один поток. Одновременно выполняются не больше двух вычислений или проверок. Отмена запроса не освобождает место в этой очереди, пока вычисление в потоке не закончится.
Сеанс
Для входа подходят логин или почта. Сеанс действует семь суток, в базе хранится хеш его случайного ключа. Браузер получает сам ключ через HttpOnly-cookie. Mini App хранит ключ в памяти страницы. Форматы запросов есть в API.md.
Выход отзывает текущий сеанс. Смена пароля, подтверждённая смена почты, включение TOTP, смена Telegram и восстановление через администратора отзывают старые сеансы. После некоторых действий сервер сразу выдаёт замену, после смены пароля и подтверждения почты нужно войти заново.
Изменяющий запрос проверяет Origin и X-Cluster-CSRF. Поля actor, profile, source, token и csrf нельзя передать в JSON-теле вместо своей принадлежности. HTTP-служба получает её из действующего сеанса.
Попытки входа ограничиваются по адресу запроса и указанному логину. Для Mini App дополнительно учитывается подписанный Telegram ID. Письма и почтовые коды имеют отдельные ограничения. Счётчики сохраняются в Mekansm и не обнуляются обычным перезапуском.
Двухэтапный вход
Подключение начинается с пароля Cluster. Ядро возвращает секрет и адрес otpauth, которые добавляются в приложение одноразовых кодов. Затем нужно отправить шестизначный код. На завершение подключения даётся десять минут.
Используется TOTP SHA-1 с периодом 30 секунд. Принимается текущий период и один соседний с каждой стороны. Уже принятый код повторно не подходит. Если два действия требуют подтверждения подряд, нужно дождаться следующего кода.
После подключения выдаётся резервный код, его хеш сохраняется в базе. Он не отключает TOTP автоматически. Восстановление выполняет оператор после проверки принадлежности профиля: auth/recover требует основание, отключает TOTP, отзывает сеансы и отправляет восстановление пароля на подтверждённую почту. Самостоятельное восстановление пароля через почту сохраняет TOTP.
Подтверждения
Для смены почты, уже привязанного Telegram-аккаунта, управления овнерами и удаления профиля нужны собственный пароль и код двухэтапного входа действующего человека. Первое подключение Telegram и управление личным ботом выполняются без повторного ввода данных входа. Дополнительный овнер подтверждает действие своими данными. Пароль первоначального овнера ему не передаётся.
Нового овнера указывают по Telegram ID. Если он ещё не зарегистрировал и не привязал профиль, возвращается registration_required. Первоначального овнера удалить нельзя. При удалении дополнительного овнера ядро закрывает всю среду терминала, чтобы прекратить и отделившиеся процессы.
Подтверждение проверяется повторно при сохранении. Если доступ отозвали во время ожидания, старый запрос не завершит изменение.
Mini App
Для входа используется initData Telegram. Ядро проверяет подпись токеном сервисного бота, возраст до пяти минут и отсутствие повторяющихся полей. Уже использованные данные входа повторно не принимаются. При подключённом TOTP нужен свежий код.
Telegram ID должен быть связан с подтверждённым профилем. Привязка требует пароль и TOTP. Если юзербот уже подключён, сменить его Telegram ID через одну привязку Mini App нельзя: нужно выполнить смену Telegram-аккаунта.
Удаление
Запрос переводит профиль в deleting. В течение семи суток удаление можно отменить с паролем и TOTP. После этого срока вход больше не принимается, даже если обслуживание ещё не удалило данные.
Ядро отзывает подключения модулей, отключает Telegram и бота, закрывает пользовательскую базу и удаляет её данные, секреты и связи профиля. От профиля остаются ID и состояние deleted.
Внешние копии не удаляются вместе с профилем. Старые записи физического журнала базы исчезают при обслуживании и уплотнении. Письма и история подписки не служат запасной копией пользовательского хранилища.
Почта
SMTP задаётся через CLUSTER_SMTP_HOST, CLUSTER_SMTP_FROM и при необходимости CLUSTER_SMTP_USER, CLUSTER_SMTP_PASSWORD. Поддержан TLS на порту 465. Настройки находятся в окружении службы, а не в исходниках.
Без SMTP очередь сохраняется, но письма не отправляются. Коды не выводятся в консоль и не возвращаются публичным запросом. После пяти неудачных доставок письмо остаётся до истечения срока; можно запросить новый код.
Для локальной проверки без почтового сервера есть cluster serve --dev-mail FILE. Флаг дописывает код в файл оператора и не включает его в ответ API. Вместе с CLUSTER_SMTP_HOST он не запускается. На общей машине его не включают.
Регистрация, TOTP и подключение Telegram требуют --key-file. Установка службы описана в DEPLOYMENT.md, методы сайта в API.md.
Юридические страницы
Сведения об исполнителе, условия использования, политика конфиденциальности и возвраты находятся по адресам #/legal/operator, #/legal/terms, #/legal/privacy и #/legal/refunds. По умолчанию они открываются на английском. В шапке доступен русский перевод; этот выбор не меняет язык панели. Дата редакции указана в документе.
При регистрации ядро сохраняет номер принятой редакции условий, время, возрастную группу и подтверждение законного представителя для группы 13-17. Изменение текста не перезаписывает сведения о ранее принятой пользователем редакции.