Cluster · разработчикам
Сайт
Сайт написан на React и TypeScript. Исходники находятся в web/src/, готовая сборка в web/dist/. Сайт работает с HTTP API ядра. В пакет cluster-core интерфейс не входит: его можно обновлять и размещать отдельно.
Сборка
Нужны Python 3.12 или новее и Node.js, совместимый с Vite 8. Зависимости закреплены в web/package-lock.json. Python собирает публичную документацию без сторонних пакетов.
cd web
npm ci
npm test
npm run buildПосле изменения исходников сборку нужно повторить. Для разработки есть npm run dev. Он проксирует /api/ на 127.0.0.1:8081; API должен принимать внешний адрес страницы через --origin. Для HTTP используй разрешённый ядром адрес http://127.0.0.1:8080; для другого адреса нужен HTTPS.
Локальный запуск
Ключ и настройки почты описаны в развёртывании. Запусти ядро, API и сайт в разных терминалах:
.venv/bin/cluster --path ./data serve --key-file /path/to/core.key
.venv/bin/cluster --path ./data api --origin http://127.0.0.1:8080 --port 8081
.venv/bin/python scripts/serve_web.py --listen 127.0.0.1:8080 --api http://127.0.0.1:8081Открой http://127.0.0.1:8080. Скрипт отдаёт web/dist/ и передаёт запросы /api/ службе API. Заголовок Origin сохраняется. Тела запросов и токены в журнал скрипта не попадают. Встроенная HTTP-служба ядра по-прежнему отдаёт только API.
Страница и API доступны браузеру по одному адресу. При обычном входе используется cookie сеанса и CSRF. В Mini App служебные токены хранятся только в памяти страницы. После выхода они удаляются; в локальное хранилище браузера записывается только выбранный язык.
Разделы
- Обзор: состояние, хранилище, подписка и порядок подключения.
- Мои модули: экземпляры, запуск, настройки, действия, команды, права и обновления.
- Каталог модулей: установка, версии, отзывы и жалобы. В «Моих публикациях» автор управляет названием, описанием, видимостью, версиями, тестерами, оформлением и удалением публикаций.
- Подключения Telegram: аккаунт, прокси и личный бот.
- Настройки и доступ: общие ограничения, овнеры, доверки и поддержка.
- Данные модулей: разделы хранилища, ключи и редактор значений.
- Файлы и резервные копии: загрузка, скачивание, создание копий и восстановление.
- Расписание действий: обработчик модуля, параметры, время и результаты выполнения.
- Обмен данными: договоры, согласование, передача и история.
- Терминал: запуск процессов, ввод, вывод и остановка.
- Журнал событий: фильтры, обновление, скачивание и очистка.
- Уведомления: события профиля и отметки о просмотре.
- Моя подписка: срок доступа, оплата, автопродление и подарочные коды.
- Профиль и безопасность: почта, пароль, TOTP, привязка Mini App и удаление профиля.
- Управление сервисом: административные операции. Раздел доступен только администратору.
- Разработчикам: создание модулей, публикация в каталоге, API и устройство ядра. Документация доступна без входа.
Поля модулей строятся по описанию интерфейса. Списки редактируются поэлементно, числовые поля с конечными границами получают ползунок. Для объектов и вложенных списков есть редактор с применением и отменой. Сохранённые секреты не возвращаются в форму. Права выбираются отдельно от ограничений по чатам, пользователям и адресам.
Доступ на сайте зависит от выбранного юзербота и роли профиля. Окончательную проверку каждого действия выполняет ядро. Скрытие пункта меню само по себе не является защитой.
Размещение
Отдавай содержимое web/dist/ статическим сервером, а /api/* направляй на API ядра. Нужен HTTPS и совпадающий --origin. Разделы панели находятся после #. Главная доступна по / на русском и /en/ на английском, юридические документы по /legal/operator, /legal/terms, /legal/privacy и /legal/refunds. Старые ссылки /#/legal/... продолжают работать.
npm run build собирает интерфейс и запускает web/prerender.mjs. Он сохраняет главную и юридические документы в HTML с текстом, описанием и основным адресом страницы. После загрузки JavaScript работают те же компоненты React. Подготовка HTML не обращается к API и не включает данные пользователей. sitemap.xml содержит только эти страницы и открытую документацию. robots.txt закрывает служебные адреса от обхода, но не заменяет авторизацию API.
Статический сервер должен отдавать /legal/terms из файла /legal/terms.html и аналогично для остальных документов. Несуществующие адреса должны возвращать HTTP 404, а не главную страницу.
Режим оплаты сайт получает из billing/info. При рабочем Stripe пользователь переходит на страницу провайдера. Тестовый режим обозначается отдельно. Ключи оплаты в сборку сайта не попадают.
Раздел /developers/ собирается из docs/ командой python3 scripts/build_docs.py. Команды npm run build и npm run dev выполняют её перед запуском Vite. После изменения документов во время разработки выполни npm run docs. Готовые страницы, примеры и карта процессов входят в web/dist/developers/. Личные справочники и черновики из домашних каталогов сборщик не использует.
Руководства из guides/ собираются той же командой в web/public/guides/, затем попадают в web/dist/guides/. У них отдельные адреса /guides/connect.html, /guides/commands.html и /guides/modules.html. Сборка добавляет руководства в карту сайта. Связанные примеры из каталога проекта копируются рядом в web/public/examples/; личные файлы не используются.
Иконки и знак Cluster нарисованы в исходниках сайта. Внешние шрифты и наборы иконок не загружаются. Уведомления о лицензиях React и его зависимостей находятся в web/public/third-party-licenses.txt и копируются в сборку.
Пример раздачи через Caddy. Пути и домен замени на свои:
cluster.example.com {
encode zstd gzip
handle /api/* {
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {remote_host}
header_up -X-Forwarded-For
}
}
handle {
root * /srv/cluster/web/dist
try_files {path} {path}.html
file_server
}
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options nosniff
Referrer-Policy same-origin
Content-Security-Policy "default-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; script-src 'self' https://telegram.org; connect-src 'self'; form-action 'self'; base-uri 'self'; frame-ancestors 'self' https://web.telegram.org https://*.telegram.org"
}
}