From d2f65b169c15fc0328128194bdc7dfc89ea333821867be180811ccd54054c87a Mon Sep 17 00:00:00 2001 From: AidarKC Date: Mon, 20 Jul 2026 17:28:35 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D0=B2=D0=B5=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20=D0=B2=20deploy=20?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- .idea/.gitignore | 8 - .idea/.name | 1 - .idea/artifacts/server_jar.xml | 10 - .idea/gradle.xml | 25 --- .idea/misc.xml | 10 - .idea/vcs.xml | 6 - AGENTS.md | 34 +-- Deploy/PRODUCTION_SERVERS.md | 93 -------- Deploy/README.md | 35 --- Deploy/TEST_SERVERS.md | 124 ----------- SHiNE-server/AGENTS.md | 20 +- .../src/main/resources/application.properties | 20 +- ...06-26_1800_корректное_завершение_за_30с.md | 2 +- ...6-05-24_1140_репосты_в_каналах_и_тредах.md | 8 +- .../2026-05-25_1106_shine_balance_wallet.md | 2 +- ...3_подключение_других_устройств_через_qr.md | 3 +- ...-05-25_1106_wallet_topup_solana_arweave.md | 2 +- .../запись_блокчейнов_в_arweave.md | 2 +- VERSION.properties | 4 +- build.gradle | 56 +---- deploy/AGENTS.md | 57 +++++ .../AGENT_BOT_CODER_LOCAL_SYSTEMD.md | 6 + deploy/CONFIGURE_TURN_IN_SHINE.md | 60 ++++++ deploy/PRODUCTION_SERVERS.md | 59 +++++ deploy/README.md | 78 +++++++ deploy/SETUP_SERVER_FROM_ZERO.md | 113 ++++++++++ deploy/SETUP_TURN_SERVER.md | 85 ++++++++ deploy/TEST_SERVERS.md | 61 ++++++ deploy/TURN_SERVERS.md | 40 ++++ {server-backup => deploy/backup}/AGENTS.md | 19 +- deploy/backup/README.md | 9 + .../backup}/archive/.gitkeep | 0 .../backup}/backup-version.properties | 0 .../shineup.me/captures/01_host_disk.txt | 0 .../captures/02_enabled_services.txt | 0 .../captures/03_running_services.txt | 0 .../shineup.me/captures/04_listen_ports.txt | 0 .../shineup.me/captures/05_docker_ps.txt | 0 .../captures/06_home_player_sizes.txt | 0 .../shineup.me/captures/07_var_sizes.txt | 0 .../shineup.me/captures/UPDATED_AT_UTC.txt | 0 .../scheme/shineup.me/configs/Caddyfile | 0 .../configs/systemd/agent-memory.service | 0 .../configs/systemd/shine-server.service | 0 .../scheme/shineup.me/configs/turnserver.conf | 2 +- .../backup}/scheme/shineup.me/docs/RESTORE.md | 18 +- .../scheme/shineup.me/scripts/backup_full.sh | 0 .../shineup.me/scripts/refresh_scheme.sh | 0 deploy/scripts/deploy_server.sh | 81 +++++++ .../scripts/deploy_ui.sh | 50 +++-- deploy/scripts/production_server2_server.sh | 10 + deploy/scripts/production_server2_ui.sh | 14 ++ deploy/scripts/production_shineupme_server.sh | 10 + .../scripts/production_shineupme_ui.sh | 3 +- .../scripts}/setup_turn_coturn.sh | 11 +- deploy/scripts/test_t1_server.sh | 9 + .../scripts/test_t1_ui.sh | 4 +- deploy/scripts/test_t2_server.sh | 9 + .../scripts/test_t2_ui.sh | 4 +- deploy/scripts/test_t3_server.sh | 9 + .../scripts/test_t3_ui.sh | 4 +- deploy/scripts/test_t4_server.sh | 9 + .../scripts/test_t4_ui.sh | 4 +- deploy_shine-server_server2shineupme.sh | 63 ------ ...oy_shine-ui_production_server2shineupme.sh | 24 --- docs/Figma/TRANSFER_UI_SCREENS.md | 4 +- ...026-06-28_1930_поддержка_проекта_сияние.md | 38 ---- .../2026-06-30_1300_promo_loginy_solana.md | 20 -- ...7-01_1945_mainnet-solana-addresses-sync.md | 51 ----- ...1_2135_временный_режим_коротких_логинов.md | 42 ---- ...26-07-09_0815_4_test_servers_devnet_vps.md | 39 ---- ...-10_1248_call_summary_dm_from_initiator.md | 17 -- ...748_dm_opaque_body_and_decrypt_fallback.md | 23 -- ...-10_1845_dm_shine_tags_and_safe_preview.md | 28 --- ..._fix_call_remote_hangup_and_ack_timeout.md | 30 --- .../2026-07-14_1745_адаптация-шапки-связей.md | 16 -- .../2026-07-14_1830_кнопка-поиска-каналов.md | 16 -- ...2026-07-14_1915_локальный-тестовый-вход.md | 20 -- ...16_1935_проверка_public_solana_rpc_в_ui.md | 23 -- ...ие_подтверждения_solana_при_регистрации.md | 20 -- docs/Pending_Features/README.md | 20 -- ...6-20_1839_registration_faq_and_12_words.md | 25 --- ...2026-06-20_2350_test_free_avatar_upload.md | 25 --- ...5_unified_channels_list_without_stories.md | 28 --- ...26-06-26_1500_addblock_tmp_bch_recovery.md | 47 ---- ...6-26_1745_proverka_avariynykh_ostanovok.md | 29 --- docs/Solana_Architecture/README.md | 2 +- docs/deploy/README.md | 95 -------- .../deploy/servers/193.8.215.70_test2_main.md | 43 ---- docs/deploy/servers/shineup.me_main.md | 48 ----- .../test-server/178.208.90.249_quad_devnet.md | 173 --------------- docs/deploy/test-server/README.md | 12 -- docs/instructions/coturn-install.md | 75 ------- .../turn-connect-to-shine-server.md | 48 ----- scripts/install_test2_caddyfile.sh | 79 ------- server-backup/README.md | 7 - .../js/pages/registration-payment-view.js | 202 +++++++++++++++++- tools/understand-anything-lab/README.md | 3 +- 99 files changed, 1035 insertions(+), 1708 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/.name delete mode 100644 .idea/artifacts/server_jar.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml delete mode 100644 Deploy/PRODUCTION_SERVERS.md delete mode 100644 Deploy/README.md delete mode 100644 Deploy/TEST_SERVERS.md create mode 100644 deploy/AGENTS.md rename docs/deploy/agent-bot-coder-local-systemd.md => deploy/AGENT_BOT_CODER_LOCAL_SYSTEMD.md (99%) create mode 100644 deploy/CONFIGURE_TURN_IN_SHINE.md create mode 100644 deploy/PRODUCTION_SERVERS.md create mode 100644 deploy/README.md create mode 100644 deploy/SETUP_SERVER_FROM_ZERO.md create mode 100644 deploy/SETUP_TURN_SERVER.md create mode 100644 deploy/TEST_SERVERS.md create mode 100644 deploy/TURN_SERVERS.md rename {server-backup => deploy/backup}/AGENTS.md (63%) create mode 100644 deploy/backup/README.md rename {server-backup => deploy/backup}/archive/.gitkeep (100%) rename {server-backup => deploy/backup}/backup-version.properties (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/01_host_disk.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/02_enabled_services.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/03_running_services.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/04_listen_ports.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/05_docker_ps.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/06_home_player_sizes.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/07_var_sizes.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/captures/UPDATED_AT_UTC.txt (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/configs/Caddyfile (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/configs/systemd/agent-memory.service (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/configs/systemd/shine-server.service (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/configs/turnserver.conf (99%) rename {server-backup => deploy/backup}/scheme/shineup.me/docs/RESTORE.md (76%) rename {server-backup => deploy/backup}/scheme/shineup.me/scripts/backup_full.sh (100%) rename {server-backup => deploy/backup}/scheme/shineup.me/scripts/refresh_scheme.sh (100%) create mode 100755 deploy/scripts/deploy_server.sh rename deploy_shine-PWA.sh => deploy/scripts/deploy_ui.sh (81%) create mode 100755 deploy/scripts/production_server2_server.sh create mode 100755 deploy/scripts/production_server2_ui.sh create mode 100755 deploy/scripts/production_shineupme_server.sh rename deploy_shine-ui_production_shineupme.sh => deploy/scripts/production_shineupme_ui.sh (87%) mode change 100644 => 100755 rename {scripts => deploy/scripts}/setup_turn_coturn.sh (81%) create mode 100755 deploy/scripts/test_t1_server.sh rename deploy_shine-ui_t1.sh => deploy/scripts/test_t1_ui.sh (81%) mode change 100644 => 100755 create mode 100755 deploy/scripts/test_t2_server.sh rename deploy_shine-ui_t2.sh => deploy/scripts/test_t2_ui.sh (81%) mode change 100644 => 100755 create mode 100755 deploy/scripts/test_t3_server.sh rename deploy_shine-ui_t3.sh => deploy/scripts/test_t3_ui.sh (81%) mode change 100644 => 100755 create mode 100755 deploy/scripts/test_t4_server.sh rename deploy_shine-ui_t4.sh => deploy/scripts/test_t4_ui.sh (81%) mode change 100644 => 100755 delete mode 100644 deploy_shine-server_server2shineupme.sh delete mode 100644 deploy_shine-ui_production_server2shineupme.sh delete mode 100644 docs/Pending_Features/2026-06-28_1930_поддержка_проекта_сияние.md delete mode 100644 docs/Pending_Features/2026-06-30_1300_promo_loginy_solana.md delete mode 100644 docs/Pending_Features/2026-07-01_1945_mainnet-solana-addresses-sync.md delete mode 100644 docs/Pending_Features/2026-07-01_2135_временный_режим_коротких_логинов.md delete mode 100644 docs/Pending_Features/2026-07-09_0815_4_test_servers_devnet_vps.md delete mode 100644 docs/Pending_Features/2026-07-10_1248_call_summary_dm_from_initiator.md delete mode 100644 docs/Pending_Features/2026-07-10_1748_dm_opaque_body_and_decrypt_fallback.md delete mode 100644 docs/Pending_Features/2026-07-10_1845_dm_shine_tags_and_safe_preview.md delete mode 100644 docs/Pending_Features/2026-07-14_1325_fix_call_remote_hangup_and_ack_timeout.md delete mode 100644 docs/Pending_Features/2026-07-14_1745_адаптация-шапки-связей.md delete mode 100644 docs/Pending_Features/2026-07-14_1830_кнопка-поиска-каналов.md delete mode 100644 docs/Pending_Features/2026-07-14_1915_локальный-тестовый-вход.md delete mode 100644 docs/Pending_Features/2026-07-16_1935_проверка_public_solana_rpc_в_ui.md delete mode 100644 docs/Pending_Features/2026-07-16_2035_ожидание_подтверждения_solana_при_регистрации.md delete mode 100644 docs/Pending_Features/README.md delete mode 100644 docs/Pending_Features/вроде сделанное/2026-06-20_1839_registration_faq_and_12_words.md delete mode 100644 docs/Pending_Features/вроде сделанное/2026-06-20_2350_test_free_avatar_upload.md delete mode 100644 docs/Pending_Features/вроде сделанное/2026-06-24_1825_unified_channels_list_without_stories.md delete mode 100644 docs/Pending_Features/вроде сделанное/2026-06-26_1500_addblock_tmp_bch_recovery.md delete mode 100644 docs/Pending_Features/вроде сделанное/2026-06-26_1745_proverka_avariynykh_ostanovok.md delete mode 100644 docs/deploy/README.md delete mode 100644 docs/deploy/servers/193.8.215.70_test2_main.md delete mode 100644 docs/deploy/servers/shineup.me_main.md delete mode 100644 docs/deploy/test-server/178.208.90.249_quad_devnet.md delete mode 100644 docs/deploy/test-server/README.md delete mode 100644 docs/instructions/coturn-install.md delete mode 100644 docs/instructions/turn-connect-to-shine-server.md delete mode 100644 scripts/install_test2_caddyfile.sh delete mode 100644 server-backup/README.md diff --git a/.gitignore b/.gitignore index 6c2b95da..962572ac 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ build/ .kotlin ### IntelliJ IDEA ### +.idea/ .idea/modules.xml .idea/jarRepositories.xml .idea/compiler.xml @@ -102,8 +103,8 @@ ESP32/**/*.d ESP32/**/*.a # Полные серверные бэкапы (тяжёлые архивы, не коммитим) -server-backup/archive/** -!server-backup/archive/.gitkeep +deploy/backup/archive/** +!deploy/backup/archive/.gitkeep # Локальная дев-обвязка Claude (дев-сервер shine-UI, сессии, планы) — не коммитим .claude/ diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index c2083d37..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 77cff8d8..00000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -shine-server-server \ No newline at end of file diff --git a/.idea/artifacts/server_jar.xml b/.idea/artifacts/server_jar.xml deleted file mode 100644 index a890428b..00000000 --- a/.idea/artifacts/server_jar.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/server_jar - - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 6a8fc097..00000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index a19bb717..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 0faa7979..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 350f9226..21aa62f4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,7 +36,7 @@ - Модуль логически связан с SHiNE, но не должен автоматически подключаться к сборке или деплою основного сервера без отдельного решения. - В Solana-модуле действуют локальные инструкции `shine-solana/shine/AGENTS.md`; при изменениях внутри модуля сначала читать их. - В git добавлять исходники, lock-файлы, настройки проекта и документацию Solana-модуля, но не добавлять локальные ключи, `.git`, `.idea`, `.gradle`, `target`, `node_modules`, `test-ledger`, логи, временные run-отчёты и `.env`-конфиги. -- Для Solana deploy/push использовать правила из локального `shine-solana/shine/AGENTS.md`; не смешивать deploy Solana-модуля с `deployServer`/`deployUI` основного проекта. +- Для Solana deploy/push использовать правила из локального `shine-solana/shine/AGENTS.md`; не смешивать deploy Solana-модуля со скриптами основного server/UI deploy из `deploy/scripts/`. - Для регистрации пользователей в Solana (программа `shine_users`) единая актуальная инструкция по деплою/инициализации, адресам программ, и куда их прописывать в UI/сервере находится в: - `docs/Инициализация_Solana_регистрации/README.md` - Этот файл считать основной справкой (single source of truth) по деплою и первичной инициализации Solana-регистрации в текущем проекте. @@ -86,18 +86,17 @@ - Обычные коммиты делать стандартным `git commit`; переменная `$GITEA_TOKEN` для коммитов не нужна и не используется. ## Deploy -- Все документы и заметки по деплою хранить в папке `Deploy/`. -- Production-хост SHiNE: `player@shineup.me` (`178.208.64.62`). -- Второй production-хост SHiNE: `player@193.8.215.70` (`server2.shineup.me`). -- Базовый путь на сервере для SHiNE: `/home/player` (проекты SHiNE размещать в `/home/player/SHiNE/...`). +- Все документы, инструкции, backup-правила и скрипты деплоя хранить в папке `deploy/`. +- Подробные правила для агента по деплою находятся в `deploy/AGENTS.md`; перед любым deploy читать этот файл. +- Production-серверы SHiNE: `shineup.me` и `server2.shineup.me`. +- Тестовые/devnet серверы SHiNE: `t1.shineup.me`, `t2.shineup.me`, `t3.shineup.me`, `t4.shineup.me`. +- В deploy-документах и скриптах использовать домены, а не IP. - По возможности все справки, комментарии и примечания в конфигах/документах писать на русском языке. - Для операций `git push` при необходимости использовать токен из переменной окружения `$GITEA_TOKEN`. -- Любые изменения и любой деплой на production `shineup.me` выполнять только после отдельного явного подтверждения пользователя. -- Если пользователь пишет просто `задеплой` без уточнения production/test, по умолчанию деплоить на `server2.shineup.me`. -- Default server deploy: `./gradlew deployServer` или `./gradlew deployServerTest2`. -- Default UI deploy: `./gradlew deployUI` или `./gradlew deployUITest2`. -- Production server deploy: `./gradlew deployServerProduction`. -- Production UI deploy: `./gradlew deployUIProduction`. +- Любые изменения и любой деплой на production (`shineup.me` и `server2.shineup.me`) выполнять только после отдельного явного подтверждения пользователя. +- Перед production deploy обязательно проверить/обновить бэкап в `deploy/backup/archive/`. +- Если пользователь пишет просто `задеплой` без уточнения production/test, уточнить целевой контур; не выбирать production автоматически. +- Deploy выполнять shell-скриптами из `deploy/scripts/`; Gradle deploy-задачи не использовать. - Для локального запуска использовать `./gradlew startLocal` (или `startLocalWithBuild`). - Сначала предлагать локальную проверку, а деплой на сервер выполнять по запросу пользователя. - Для временной бесплатной загрузки аватаров в Arweave секретный JWK нельзя хранить в git и нельзя прописывать в репозиторный `application.properties`. @@ -123,19 +122,6 @@ - `unknown_error` - В этих записях искать поля `reason`, `failureStage`, `pcConnectionState`, `pcIceConnectionState`, `routeLabel`, `configuredTurnHosts*`, `reachableTurnHosts*`. -## Недопроверенные фичи (обязательно) -- Папка для учёта недопроверенных фич: `docs/Pending_Features/`. -- По каждой новой доработке, которая требует ручной проверки, добавлять отдельный markdown-файл в `docs/Pending_Features/`. -- Рекомендуемый формат имени файла: `YYYY-MM-DD_HHMM_.md`. -- Имена новых файлов и краткие описания фич по возможности писать на русском языке. -- Внутри файла обязательно указывать: - - краткое описание фичи; - - что именно проверять; - - ожидаемый результат; - - статус (например: `pending`, `in_progress`, `done`). -- После подтверждения, что фича проверена и работает корректно, соответствующий файл удалять. -- В `docs/Pending_Features/README.md` вести краткий регламент и поддерживать актуальность. - ## Будущие фичи / TODO - Папка для задач, сознательно отложенных на будущее: `TODO/`. - Точка входа по планам: `TODO/README.md`. diff --git a/Deploy/PRODUCTION_SERVERS.md b/Deploy/PRODUCTION_SERVERS.md deleted file mode 100644 index a3177b51..00000000 --- a/Deploy/PRODUCTION_SERVERS.md +++ /dev/null @@ -1,93 +0,0 @@ -# Production-серверы SHiNE - -## Короткий ответ - -По текущим данным репозитория у SHiNE описаны **два production-контура**: - -- `player@shineup.me` -- домен `shineup.me` -- IP `178.208.64.62` - -и - -- `player@193.8.215.70` -- домен `server2.shineup.me` -- IP `193.8.215.70` - -## 1. Основной production-хост - -- SSH: `player@shineup.me` -- домен: `shineup.me` -- IP: `178.208.64.62` -- пользователь: `player` -- базовый путь: `/home/player` - -Основные каталоги: - -- проект SHiNE: `/home/player/SHiNE` -- серверный jar: `/home/player/SHiNE/shine-server/shine-server.jar` -- UI: `/home/player/SHiNE/shine-ui` -- данные: `/home/player/SHiNE/shine-server/data/` -- логи: `/home/player/SHiNE/shine-server/logs/app.log` - -Сервисы: - -- `shine-server.service` -- `caddy.service` - -Caddy: - -- активный конфиг: `/etc/caddy/Caddyfile` -- UI root: `/home/player/SHiNE/shine-ui` -- `/ws` проксируется на `127.0.0.1:7070` - -Deploy: - -- `./gradlew deployServerProduction` -- `./gradlew deployUIProduction` - -Правило: - -- любые изменения на `shineup.me` делать только после отдельного подтверждения пользователя. - -## 2. Второй production-сервер - -- SSH: `player@193.8.215.70` -- домен: `server2.shineup.me` -- IP: `193.8.215.70` -- пользователь: `player` -- базовый путь: `/home/player` - -Роль: - -- второй production-контур SHiNE; -- использовать как production-сервер, несмотря на исторические имена deploy-задач - `deployServerTest2` / `deployUITest2`. - -Основные каталоги: - -- проект SHiNE: `/home/player/SHiNE` -- серверный jar: `/home/player/SHiNE/shine-server/shine-server.jar` -- UI: `/home/player/SHiNE/shine-ui` -- данные: `/home/player/SHiNE/shine-server/data/` -- логи: `/home/player/SHiNE/shine-server/logs/app.log` - -## 3. Связанные публичные production-публикации на том же хосте - -На этом же production-хосте есть отдельная публикация для `shine_payments`: - -- каталог: `/home/player/sites/test-solana-tickets.shineup.me` -- домены: - - `https://test-solana-tickets.shineup.me` - - `https://test-solana-tickets.shiningpeople.ru` - -Это не второй production-хост SHiNE, а отдельный сайт на том же сервере. - -## 4. Какие серверы не считать production - -Не production: - -- `t1.shineup.me` -- `t2.shineup.me` -- `t3.shineup.me` -- `t4.shineup.me` diff --git a/Deploy/README.md b/Deploy/README.md deleted file mode 100644 index 0f730fcf..00000000 --- a/Deploy/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Deploy - -Подробности о том, где что задеплоено в SHiNE, нужно искать в папке `Deploy/`. - -Эта папка служит краткой картой окружений: - -- [TEST_SERVERS.md](/home/ai/work/SHiNE/SHiNE-server-sha256/Deploy/TEST_SERVERS.md) — тестовые стенды; -- [PRODUCTION_SERVERS.md](/home/ai/work/SHiNE/SHiNE-server-sha256/Deploy/PRODUCTION_SERVERS.md) — production-контур и связанные публичные публикации. - -Ниже краткая сводка. - -## Основные публичные контуры - -- Production SHiNE: - - `player@shineup.me` - - домен `shineup.me` - - IP `178.208.64.62` -- Второй production SHiNE: - - `player@193.8.215.70` - - домен `server2.shineup.me` - - IP `193.8.215.70` -## Отдельный quad-devnet стенд - -На отдельном VPS `178.208.90.249` подняты 4 независимых test/devnet-инстанса: - -- `t1.shineup.me` -- `t2.shineup.me` -- `t3.shineup.me` -- `t4.shineup.me` - -## Важно - -- Production-контура SHiNE сейчас два: `shineup.me` и `server2.shineup.me`. -- `t1..t4.shineup.me` — это отдельные тестовые/devnet-контуры, не production. -- Любые изменения на `shineup.me` делать только после отдельного подтверждения пользователя. diff --git a/Deploy/TEST_SERVERS.md b/Deploy/TEST_SERVERS.md deleted file mode 100644 index eb214bb2..00000000 --- a/Deploy/TEST_SERVERS.md +++ /dev/null @@ -1,124 +0,0 @@ -# Тестовые серверы SHiNE - -Этот файл описывает тестовые стенды, которые сейчас фигурируют в проекте. - -## 1. Исторический `test2`, теперь второй production-сервер - -- SSH: `player@193.8.215.70` -- Домен: `server2.shineup.me` -- IP: `193.8.215.70` -- Назначение: второй production-контур SHiNE - -Структура: - -- каталог SHiNE: `/home/player/SHiNE` -- сервер: `/home/player/SHiNE/shine-server/shine-server.jar` -- UI: `/home/player/SHiNE/shine-ui` -- данные: `/home/player/SHiNE/shine-server/data/` -- логи: `/home/player/SHiNE/shine-server/logs/app.log` - -Сервисы: - -- `shine-server.service` -- `caddy.service` - -Deploy: - -- `./gradlew deployServer` -- `./gradlew deployServerTest2` -- `./gradlew deployUI` -- `./gradlew deployUITest2` - -Примечания: - -- этот хост больше не считать test-контуром; -- исторические имена deploy-задач `deployServerTest2` / `deployUITest2` сохранены, но сам хост считать production; -- задача `deployUITest2` по умолчанию выкладывает UI на `server2.shineup.me`, а не на `t2.shineup.me`; -- при описании окружений перечислять его как второй production-сервер. - -## 2. Отдельный quad-devnet стенд `t1..t4` - -- VPS: `178.208.90.249` -- пользователь: `player` -- назначение: 4 независимых SHiNE-инстанса на Solana `devnet` - -Домены и логины: - -- `server_t1` -> `https://t1.shineup.me` -- `server_t2` -> `https://t2.shineup.me` -- `server_t3` -> `https://t3.shineup.me` -- `server_t4` -> `https://t4.shineup.me` - -Каталоги: - -- `/home/player/t1/server` -- `/home/player/t1/UI` -- `/home/player/t2/server` -- `/home/player/t2/UI` -- `/home/player/t3/server` -- `/home/player/t3/UI` -- `/home/player/t4/server` -- `/home/player/t4/UI` - -Подробная памятка на самом VPS: - -- `/home/player/Agents.md` - -Порты и systemd: - -- `t1` -> `7101` -> `shine-t1.service` -- `t2` -> `7102` -> `shine-t2.service` -- `t3` -> `7103` -> `shine-t3.service` -- `t4` -> `7104` -> `shine-t4.service` - -Что важно по конфигу каждого инстанса: - -- отдельный `/home/player/tX/server/application.properties` -- `server.port=710X` -- `server.SHiNE.login=server_tX` -- `db.path=data/shine.sqlite` -- `solana.cluster=devnet` -- `solana.rpcUrl=https://api.devnet.solana.com` -- `server.ui.indexPath=/home/player/tX/UI/index.html` -- `server.info.url=https://tX.shineup.me` - -UI каждого инстанса: - -- живёт в отдельной копии `shine-UI`; -- использует свой `js/deploy-config.js`; -- по умолчанию смотрит именно на свой `tX.shineup.me`. - -Caddy на стенде: - -- конфиг: `/etc/caddy/Caddyfile` -- статика: `/home/player/tX/UI` -- `/ws` проксируется на `127.0.0.1:710X` - -Operational-нюанс: - -- при одновременных рестартах возможны `HTTP 429` от `api.devnet.solana.com`; -- поэтому сервисы `shine-t1..shine-t4` лучше перезапускать по одному, с паузой. - -## 3. Что проверять первым делом - -Для любого test-контура полезны такие быстрые проверки: - -```bash -curl -I https://server2.shineup.me -curl -I https://t1.shineup.me -curl -I https://t2.shineup.me -curl -I https://t3.shineup.me -curl -I https://t4.shineup.me -``` - -Для quad-devnet VPS: - -```bash -sudo systemctl --no-pager --full status caddy shine-t1 shine-t2 shine-t3 shine-t4 -``` - -Для второго production-контура: - -```bash -sudo systemctl --no-pager --full status shine-server caddy -``` diff --git a/SHiNE-server/AGENTS.md b/SHiNE-server/AGENTS.md index 357a5731..573f3bea 100644 --- a/SHiNE-server/AGENTS.md +++ b/SHiNE-server/AGENTS.md @@ -54,21 +54,11 @@ shine-UI/server-ui.html ## Деплой -``` -./gradlew deployServer -./gradlew deployUI -``` - -Default deploy по умолчанию идёт на `server2.shineup.me` (`player@193.8.215.70`). - -Production deploy: - -``` -./gradlew deployServerProduction -./gradlew deployUIProduction -``` - -Любые изменения на `shineup.me` делать только после отдельного явного подтверждения пользователя. +- Основные инструкции по деплою находятся в `../deploy/AGENTS.md`. +- Deploy выполнять shell-скриптами из `../deploy/scripts/`. +- Gradle deploy-задачи не использовать: Gradle остаётся для сборки и локального запуска. +- Любые изменения на production (`shineup.me`, `server2.shineup.me`) делать только после отдельного явного подтверждения пользователя. +- Перед production deploy обязательно обновить/проверить backup в `deploy/backup/archive/`. Логи на проде: - `/home/player/SHiNE/shine-server/logs/app.log` diff --git a/SHiNE-server/src/main/resources/application.properties b/SHiNE-server/src/main/resources/application.properties index 307739f3..b910adbd 100644 --- a/SHiNE-server/src/main/resources/application.properties +++ b/SHiNE-server/src/main/resources/application.properties @@ -44,7 +44,7 @@ webpush.vapid.subject=mailto:admin@shine.local # Тогда сервер будет выдавать временный username/password (TTL). # ------------------------------------------------------------ call.ice.stun.urls=stun:stun.l.google.com:19302 -call.ice.turn.urls=turn:185.229.109.118:3478?transport=udp,turn:185.229.109.118:3478?transport=tcp +call.ice.turn.urls=turn:turn1.shineup.me:3478?transport=udp,turn:turn1.shineup.me:3478?transport=tcp call.ice.turn.ttlSec=600 call.ice.turn.userPrefix=shine call.ice.turn.sharedSecret= @@ -58,12 +58,24 @@ call.ice.turn.password= # Каждый блок описывает один TURN-узел. Новые узлы добавляются по индексу. # Приоритет авторизации на узел: sharedSecret -> статические username/password. # ------------------------------------------------------------ -call.ice.turn.servers.1.id=shineup-main-185 -call.ice.turn.servers.1.urls=turn:185.229.109.118:3478?transport=udp,turn:185.229.109.118:3478?transport=tcp -call.ice.turn.servers.1.sharedSecret=def6d444734d380d2f67a9d345b1debf985eaba0973c343e392c060d97c30106 +call.ice.turn.servers.1.id=turn1 +call.ice.turn.servers.1.urls=turn:turn1.shineup.me:3478?transport=udp,turn:turn1.shineup.me:3478?transport=tcp +call.ice.turn.servers.1.sharedSecret= call.ice.turn.servers.1.username= call.ice.turn.servers.1.password= +call.ice.turn.servers.2.id=turn2 +call.ice.turn.servers.2.urls=turn:turn2.shineup.me:3478?transport=udp,turn:turn2.shineup.me:3478?transport=tcp +call.ice.turn.servers.2.sharedSecret= +call.ice.turn.servers.2.username= +call.ice.turn.servers.2.password= + +call.ice.turn.servers.3.id=turn3 +call.ice.turn.servers.3.urls=turn:turn3.shineup.me:3478?transport=udp,turn:turn3.shineup.me:3478?transport=tcp +call.ice.turn.servers.3.sharedSecret= +call.ice.turn.servers.3.username= +call.ice.turn.servers.3.password= + # ------------------------------------------------------------ # Временные debug HTTP API для тестирования соединений # true - endpoint'ы /debug/ws/* включены (только при наличии .debug-token) diff --git a/TODO/2026-06-26_1800_корректное_завершение_за_30с.md b/TODO/2026-06-26_1800_корректное_завершение_за_30с.md index 8a786128..c525498b 100644 --- a/TODO/2026-06-26_1800_корректное_завершение_за_30с.md +++ b/TODO/2026-06-26_1800_корректное_завершение_за_30с.md @@ -35,5 +35,5 @@ ## Какие документы потом обновить -- `Deploy/`; +- `deploy/`; - `docs/Blockchain/sync-between-servers.md`, если изменится поведение остановки/восстановления. diff --git a/TODO/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md b/TODO/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md index 4d845621..cc980c7e 100644 --- a/TODO/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md +++ b/TODO/medium/2026-05-24_1140_репосты_в_каналах_и_тредах.md @@ -56,11 +56,9 @@ - Код формирования репоста в `auth-service.js` не удалён: его можно будет использовать как основу при возвращении к задаче. - Код отображения target-полей и перехода к оригиналу не удалён: он нужен для будущей проверки и возможной совместимости с уже созданными тестовыми блоками. -## Почему это не лежит в Pending_Features +## Почему это лежит в TODO -`docs/Pending_Features/` предназначена для фич, которые уже реализованы и ждут ручной проверки. - -Репосты сейчас не подходят под этот статус: они не должны проверяться как готовая фича, потому что пользовательский сценарий временно закрыт, а серверная запись новых репостов заблокирована. Поэтому старый pending-файл удалён, а задача перенесена сюда как будущая. +Репосты сейчас не должны проверяться как готовая фича, потому что пользовательский сценарий временно закрыт, а серверная запись новых репостов заблокирована. Поэтому задача остаётся в TODO как будущая. ## Что сделать при возврате к реализации @@ -86,7 +84,7 @@ - `docs/Blockchain/CHANGELOG.md`; - `docs/API/04_Add_Block_to_Blockchain_API.md`; - документы API чтения каналов/тредов, если изменятся поля ответа. -9. После реализации перенести задачу из `TODO/` в `docs/Pending_Features/` как фичу, требующую ручной проверки. +9. После реализации отдельно согласовать ручную проверку пользовательского сценария. ## Минимальный чек-лист ручной проверки в будущем diff --git a/TODO/medium/2026-05-25_1106_shine_balance_wallet.md b/TODO/medium/2026-05-25_1106_shine_balance_wallet.md index 05ead4ad..cb735c8b 100644 --- a/TODO/medium/2026-05-25_1106_shine_balance_wallet.md +++ b/TODO/medium/2026-05-25_1106_shine_balance_wallet.md @@ -50,7 +50,7 @@ - `docs/Blockchain/`, если появятся или изменятся блоки баланса. - `docs/Blockchain/CHANGELOG.md`, если меняется блокчейн-формат. - `docs/API/`, если меняется серверный API. -- `docs/Pending_Features/` - добавить файл ручной проверки после реализации. +- после реализации отдельно согласовать ручную проверку. - Документацию Solana-регистрации, если баланс будет связан с Solana-модулем. ## Минимальная проверка в будущем diff --git a/TODO/medium/2026-06-03_подключение_других_устройств_через_qr.md b/TODO/medium/2026-06-03_подключение_других_устройств_через_qr.md index b57d06f9..12d561b6 100644 --- a/TODO/medium/2026-06-03_подключение_других_устройств_через_qr.md +++ b/TODO/medium/2026-06-03_подключение_других_устройств_через_qr.md @@ -37,9 +37,8 @@ ## Что обновить при возврате -- `docs/Pending_Features/README.md` +- после реализации отдельно согласовать ручную проверку - `shine-UI/js/pages/connect-device-view.js` - `shine-UI/js/pages/device-qr-view.js` - `shine-UI/js/services/qr-key-transfer-service.js` - документацию по ключам, если формат переноса меняется - diff --git a/TODO/near/2026-05-25_1106_wallet_topup_solana_arweave.md b/TODO/near/2026-05-25_1106_wallet_topup_solana_arweave.md index 2d228ac6..4de664eb 100644 --- a/TODO/near/2026-05-25_1106_wallet_topup_solana_arweave.md +++ b/TODO/near/2026-05-25_1106_wallet_topup_solana_arweave.md @@ -58,7 +58,7 @@ ## Документы, которые обновить при реализации - Документацию UI/кошельков, если такая есть. -- `docs/Pending_Features/` - добавить файл ручной проверки после реализации. +- после реализации отдельно согласовать ручную проверку. - `docs/API/`, только если появится новый серверный API или логирование. ## Минимальная проверка diff --git a/TODO/Децентрализация/запись_блокчейнов_в_arweave.md b/TODO/Децентрализация/запись_блокчейнов_в_arweave.md index b0bf088f..1d702707 100644 --- a/TODO/Децентрализация/запись_блокчейнов_в_arweave.md +++ b/TODO/Децентрализация/запись_блокчейнов_в_arweave.md @@ -22,7 +22,7 @@ - `docs/Blockchain/README.md`; - `docs/Blockchain/CHANGELOG.md`; -- документы deploy/секретов в `Deploy/`, если появятся новые параметры. +- документы deploy/секретов в `deploy/`, если появятся новые параметры. ## Статус diff --git a/VERSION.properties b/VERSION.properties index aac20b46..4c15330c 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.2.330 -server.version=1.2.302 +client.version=1.2.331 +server.version=1.2.303 diff --git a/build.gradle b/build.gradle index 3c786e10..8014732a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' id 'application' -проверь ещё id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.github.johnrengelman.shadow' version '8.1.1' } def appVersionProps = new Properties() @@ -185,60 +185,6 @@ tasks.named('build') { finalizedBy tasks.named('integrationTest') } -tasks.register('deployServerProduction', JavaExec) { - group = "!!deployment" - description = "Production deploy: build → upload to shineup.me → restart service (только после явного подтверждения)" - - classpath = sourceSets.test.runtimeClasspath - mainClass = "test.it.IT_DeployRestartNoCleanNoTestsMain" - workingDir = file('SHiNE-server') - - dependsOn shadowJar - systemProperty "it.remoteHost", System.getProperty("it.remoteHost", "shineup.me") - systemProperty "it.remoteUser", System.getProperty("it.remoteUser", "player") - systemProperty "it.remoteDir", System.getProperty("it.remoteDir", "/home/player/SHiNE/shine-server") - systemProperty "it.service", System.getProperty("it.service", "shine-server") - systemProperty "it.localJar", System.getProperty("it.localJar", "build/libs/shine-server.jar") - - dependsOn testClasses -} - -tasks.register('deployUIProduction', Exec) { - group = "!!deployment" - description = "Production UI deploy: shineup.me (только после явного подтверждения)" - workingDir = rootDir - commandLine 'bash', file('deploy_shine-ui_production_shineupme.sh').absolutePath -} - -tasks.register('deployServer', Exec) { - group = "!!deployment" - description = "Default deploy server: server2.shineup.me" - dependsOn shadowJar - workingDir = rootDir - environment 'LOCAL_JAR', file('SHiNE-server/build/libs/shine-server.jar').absolutePath - commandLine 'bash', file('deploy_shine-server_server2shineupme.sh').absolutePath -} - -tasks.register('deployUI', Exec) { - group = "!!deployment" - description = "Default deploy UI: server2.shineup.me" - workingDir = rootDir - commandLine 'bash', file('deploy_shine-ui_production_server2shineupme.sh').absolutePath -} - -tasks.register('deployServerTest2') { - group = "!!deployment" - description = "Явный алиас второго production deploy server: server2.shineup.me" - dependsOn tasks.named('deployServer') -} - -tasks.register('deployUITest2') { - group = "!!deployment" - description = "Явный алиас второго production deploy UI: server2.shineup.me" - dependsOn tasks.named('deployUI') -} - - tasks.register('startLocal', Exec) { group = "!!run" description = "Builds server, starts local WS server and local HTTP UI for end-to-end local testing" diff --git a/deploy/AGENTS.md b/deploy/AGENTS.md new file mode 100644 index 00000000..f83d1ee0 --- /dev/null +++ b/deploy/AGENTS.md @@ -0,0 +1,57 @@ +# AGENTS для deploy + +## Главное + +- Все вопросы деплоя SHiNE решать через эту папку `deploy/`. +- Скрипты лежат в `deploy/scripts/`. +- Production-серверы: `shineup.me` и `server2.shineup.me`. +- Test/devnet серверы: `t1.shineup.me`, `t2.shineup.me`, `t3.shineup.me`, `t4.shineup.me`. +- TURN-серверы: `turn1.shineup.me`, `turn2.shineup.me`, `turn3.shineup.me`. +- В deploy-документах и скриптах использовать домены, а не IP. + +## Production safety + +- Любой deploy на `shineup.me` или `server2.shineup.me` выполнять только после отдельного явного подтверждения пользователя. +- Перед production deploy обязательно проверить, что свежий бэкап лежит в `deploy/backup/archive/`. +- Production wrappers требуют наличие `deploy/backup/archive//MANIFEST.txt`. +- Секреты, `.env`, JWK, TURN shared secrets и приватные ключи не коммитить. + +## Как деплоить + +Сервер: + +```bash +bash deploy/scripts/_server.sh +``` + +UI: + +```bash +bash deploy/scripts/_ui.sh +``` + +Для настоящего `t2.shineup.me` использовать: + +```bash +bash deploy/scripts/test_t2_server.sh +bash deploy/scripts/test_t2_ui.sh +``` + +Не путать `server2.shineup.me` и `t2.shineup.me`. + +## Документы + +- `README.md` — карта deploy-папки. +- `PRODUCTION_SERVERS.md` — production. +- `TEST_SERVERS.md` — test/devnet. +- `TURN_SERVERS.md` — TURN. +- `CONFIGURE_TURN_IN_SHINE.md` — подключение TURN к SHiNE backend. +- `SETUP_SERVER_FROM_ZERO.md` — сервер + Caddy + UI с нуля. +- `SETUP_TURN_SERVER.md` — TURN с нуля. +- `backup/README.md` — backup. + +## Gradle + +- Gradle deploy-задачи удалены. +- Для сборки jar общий server deploy script вызывает `./gradlew shadowJar`. +- Для локального запуска можно использовать `./gradlew startLocal`. diff --git a/docs/deploy/agent-bot-coder-local-systemd.md b/deploy/AGENT_BOT_CODER_LOCAL_SYSTEMD.md similarity index 99% rename from docs/deploy/agent-bot-coder-local-systemd.md rename to deploy/AGENT_BOT_CODER_LOCAL_SYSTEMD.md index bc446945..d458841c 100644 --- a/docs/deploy/agent-bot-coder-local-systemd.md +++ b/deploy/AGENT_BOT_CODER_LOCAL_SYSTEMD.md @@ -1,17 +1,20 @@ # Локальный деплой SHiNE-agent-bot-coder (systemd, пользователь ai) ## Где находится сервис + - Папка сервиса: `SHiNE-agent-bot-coder/` - Systemd unit: `SHiNE-agent-bot-coder/scripts/systemd/shine-agent-bot-coder.service` - Скрипт установки: `SHiNE-agent-bot-coder/scripts/systemd/install-local-systemd.sh` ## Предусловия + 1. Заполнен `.env` на основе `.env.example`. 2. Доступен рабочий Codex CLI: - `/home/ai/.cache/JetBrains/IntelliJIdea2026.1/aia/codex/bin/codex-x86_64-unknown-linux-musl` 3. На машине установлен `systemd --user`. ## Установка + Из корня репозитория: ```bash @@ -19,18 +22,21 @@ bash SHiNE-agent-bot-coder/scripts/systemd/install-local-systemd.sh ``` Скрипт: + 1. проверяет наличие `python3`; 2. копирует unit в `~/.config/systemd/user/`; 3. делает `systemctl --user daemon-reload`; 4. включает автозапуск и стартует сервис. ## Проверка + ```bash systemctl --user status shine-agent-bot-coder --no-pager journalctl --user -u shine-agent-bot-coder -f ``` ## Перезапуск после изменений + ```bash systemctl --user restart shine-agent-bot-coder ``` diff --git a/deploy/CONFIGURE_TURN_IN_SHINE.md b/deploy/CONFIGURE_TURN_IN_SHINE.md new file mode 100644 index 00000000..d35fb917 --- /dev/null +++ b/deploy/CONFIGURE_TURN_IN_SHINE.md @@ -0,0 +1,60 @@ +# Подключение TURN к SHiNE-серверу + +Клиент звонков запрашивает ICE-конфиг у backend через WS-операцию `GetCallIceConfig` и использует её для `RTCPeerConnection`. + +## Репозиторный конфиг + +В `SHiNE-server/src/main/resources/application.properties` можно хранить только публичные домены и пустые placeholders. + +Пример: + +```properties +call.ice.stun.urls=stun:stun.l.google.com:19302 +call.ice.turn.urls=turn:turn1.shineup.me:3478?transport=udp,turn:turn1.shineup.me:3478?transport=tcp +call.ice.turn.ttlSec=600 +call.ice.turn.userPrefix=shine +call.ice.turn.sharedSecret= + +call.ice.turn.servers.1.id=turn1 +call.ice.turn.servers.1.urls=turn:turn1.shineup.me:3478?transport=udp,turn:turn1.shineup.me:3478?transport=tcp +call.ice.turn.servers.1.sharedSecret= +``` + +## Production override + +Реальные `sharedSecret`, статические логины/пароли и другие секреты задавать только на сервере через внешний `application.properties` или override-конфиг. В git их не хранить. + +Рекомендуемый режим: + +- на coturn включить `use-auth-secret`; +- в coturn задать `static-auth-secret=`; +- в SHiNE-сервере задать такой же `call.ice.turn.sharedSecret` или `call.ice.turn.servers.N.sharedSecret`; +- сервер будет выдавать короткоживущие `turnUsername` / `turnPassword` с TTL. + +Fallback-режим: + +```properties +call.ice.turn.sharedSecret= +call.ice.turn.username=turn_user +call.ice.turn.password=turn_password +``` + +Fallback тоже не должен хранить реальные credentials в git. + +## Деплой после изменения TURN-настроек + +Для production сначала обновить бэкап в `deploy/backup/archive/`, затем выполнить нужный server deploy script: + +```bash +bash deploy/scripts/production_shineupme_server.sh +``` + +Если менялись только серверные TURN-настройки во внешнем override-конфиге, достаточно перезапустить соответствующий `shine-server.service`. + +## Проверка звонка + +1. Авторизоваться двумя клиентами. +2. Запустить звонок. +3. Проверить, что звонок устанавливается в сети, где прямой P2P затруднён. +4. В диагностике звонков смотреть `CallDeliveryReport`, `pcIceConnectionState`, `routeLabel`, `configuredTurnHosts*`, `reachableTurnHosts*`. +5. Если TURN недоступен, клиент должен откатиться к STUN-конфигу по умолчанию. diff --git a/deploy/PRODUCTION_SERVERS.md b/deploy/PRODUCTION_SERVERS.md new file mode 100644 index 00000000..0d9b82d9 --- /dev/null +++ b/deploy/PRODUCTION_SERVERS.md @@ -0,0 +1,59 @@ +# Production-серверы SHiNE + +Production-контуров два. В документах и скриптах использовать домены, а не IP: физический VPS можно заменить без изменения deploy-логики. + +## Основной production + +- Домен: `shineup.me` +- SSH: `player@shineup.me` +- Логин сервера SHiNE: `shineupme` +- Базовый каталог: `/home/player/SHiNE` +- Сервер: `/home/player/SHiNE/shine-server/shine-server.jar` +- UI: `/home/player/SHiNE/shine-ui` +- Данные: `/home/player/SHiNE/shine-server/data/` +- Логи: `/home/player/SHiNE/shine-server/logs/app.log` +- systemd service: `shine-server.service` +- Caddy site: `shineup.me` +- WebSocket: `/ws` -> `127.0.0.1:7070` +- Solana cluster: `mainnet-beta` + +Deploy: + +```bash +bash deploy/scripts/production_shineupme_server.sh +bash deploy/scripts/production_shineupme_ui.sh +``` + +## Второй production + +- Домен: `server2.shineup.me` +- SSH: `player@server2.shineup.me` +- Логин сервера SHiNE: `server2shineupme` +- Базовый каталог: `/home/player/SHiNE` +- Сервер: `/home/player/SHiNE/shine-server/shine-server.jar` +- UI: `/home/player/SHiNE/shine-ui` +- Данные: `/home/player/SHiNE/shine-server/data/` +- Логи: `/home/player/SHiNE/shine-server/logs/app.log` +- systemd service: `shine-server.service` +- Caddy site: `server2.shineup.me` +- WebSocket: `/ws` -> `127.0.0.1:7070` +- Solana cluster: `mainnet-beta` + +Deploy: + +```bash +bash deploy/scripts/production_server2_server.sh +bash deploy/scripts/production_server2_ui.sh +``` + +## Обязательное правило backup + +Перед любым production deploy нужно обновить локальный бэкап в `deploy/backup/archive/`. + +Production wrappers проверяют наличие `MANIFEST.txt` в `deploy/backup/archive//`. Если свежий бэкап не скопирован, deploy должен быть остановлен. + +## Запрещено + +- Не использовать IP как основной target deploy. +- Не возвращать старые deploy-алиасы с названием `test2`. +- Не считать `t2.shineup.me` вторым production: это test/devnet. diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 00000000..78bd95ba --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,78 @@ +# Deploy SHiNE + +Эта папка — единая точка входа по деплою SHiNE. + +## Правило + +- Все deploy-документы, deploy-скрипты и backup-инструкции держать здесь. +- Deploy-привязки задавать через домены, а не через IP. +- Production-серверы менять только после отдельного явного подтверждения пользователя. +- Production deploy выполнять только после обновления локального бэкапа в `deploy/backup/archive/`. + +## Контуры + +- Основной production: `shineup.me`. +- Второй production: `server2.shineup.me`. +- Test/devnet стенд: `t1.shineup.me`, `t2.shineup.me`, `t3.shineup.me`, `t4.shineup.me`. + +## Основные документы + +- `PRODUCTION_SERVERS.md` — production-контуры. +- `TEST_SERVERS.md` — test/devnet-контуры. +- `TURN_SERVERS.md` — TURN-серверы. +- `CONFIGURE_TURN_IN_SHINE.md` — как подключить TURN к SHiNE backend. +- `SETUP_SERVER_FROM_ZERO.md` — настройка SHiNE-сервера и UI с нуля. +- `SETUP_TURN_SERVER.md` — настройка TURN через Caddy/DNS/TLS. +- `AGENT_BOT_CODER_LOCAL_SYSTEMD.md` — локальный systemd-deploy Telegram-бота агента-кодера. +- `AGENTS.md` — правила для агента при деплое. + +## Скрипты + +Общие скрипты: + +- `scripts/deploy_server.sh` — обновить существующий серверный jar и перезапустить systemd service. +- `scripts/deploy_ui.sh` — обновить существующий UI, проверить Caddy root и подставить `deploy-config.js`. + +Production wrappers: + +- `scripts/production_shineupme_server.sh` +- `scripts/production_shineupme_ui.sh` +- `scripts/production_server2_server.sh` +- `scripts/production_server2_ui.sh` + +Test/devnet wrappers: + +- `scripts/test_t1_server.sh` +- `scripts/test_t1_ui.sh` +- `scripts/test_t2_server.sh` +- `scripts/test_t2_ui.sh` +- `scripts/test_t3_server.sh` +- `scripts/test_t3_ui.sh` +- `scripts/test_t4_server.sh` +- `scripts/test_t4_ui.sh` + +## Примеры + +UI на настоящий тестовый `t2.shineup.me`: + +```bash +bash deploy/scripts/test_t2_ui.sh +``` + +Сервер на настоящий тестовый `t2.shineup.me`: + +```bash +bash deploy/scripts/test_t2_server.sh +``` + +Production UI на `server2.shineup.me`: + +```bash +bash deploy/scripts/production_server2_ui.sh +``` + +Production server на `shineup.me`: + +```bash +bash deploy/scripts/production_shineupme_server.sh +``` diff --git a/deploy/SETUP_SERVER_FROM_ZERO.md b/deploy/SETUP_SERVER_FROM_ZERO.md new file mode 100644 index 00000000..de4b6f6d --- /dev/null +++ b/deploy/SETUP_SERVER_FROM_ZERO.md @@ -0,0 +1,113 @@ +# Настройка SHiNE-сервера с нуля + +Инструкция описывает базовую подготовку существующего Linux/VPS-хоста под SHiNE server + UI. Привязка должна идти к домену, а не к IP. + +## 1. DNS + +Создать DNS-запись домена: + +- production: `shineup.me` или `server2.shineup.me`; +- test/devnet: `t1.shineup.me` ... `t4.shineup.me`. + +После смены физического сервера достаточно обновить DNS. + +## 2. Пользователь и пакеты + +```bash +sudo apt update +sudo apt install -y openjdk-17-jre-headless rsync caddy +sudo useradd -m -s /bin/bash player || true +``` + +## 3. Каталоги + +Production: + +```bash +mkdir -p /home/player/SHiNE/shine-server/data +mkdir -p /home/player/SHiNE/shine-server/logs +mkdir -p /home/player/SHiNE/shine-ui +``` + +Test/devnet: + +```bash +mkdir -p /home/player/tX/server/data +mkdir -p /home/player/tX/server/logs +mkdir -p /home/player/tX/UI +``` + +## 4. application.properties + +Каждый сервер должен иметь локальный внешний конфиг в рабочей директории сервиса. + +Production пример: + +```properties +server.port=7070 +server.SHiNE.login=shineupme +db.path=data/shine.sqlite +server.ui.indexPath=/home/player/SHiNE/shine-ui/index.html +server.info.url=https://shineup.me +server.info.origin=production +solana.cluster=mainnet-beta +``` + +Test/devnet пример: + +```properties +server.port=7102 +server.SHiNE.login=server_t2 +db.path=data/shine.sqlite +server.ui.indexPath=/home/player/t2/UI/index.html +server.info.url=https://t2.shineup.me +server.info.origin=devnet +solana.cluster=devnet +solana.rpcUrl=https://api.devnet.solana.com +``` + +## 5. Caddy + +Минимальный site block: + +```caddyfile +t2.shineup.me { + encode zstd gzip + + @ws path /ws /ws/* + handle @ws { + reverse_proxy 127.0.0.1:7102 + } + + handle { + root * /home/player/t2/UI + try_files {path} /index.html + file_server + header -Etag + header { + Cache-Control "no-store, no-cache, must-revalidate, max-age=0" + Pragma "no-cache" + Expires "0" + } + } +} +``` + +Проверка: + +```bash +sudo caddy validate --config /etc/caddy/Caddyfile +sudo systemctl restart caddy +curl -I https://t2.shineup.me +``` + +## 6. Первый deploy + +Из репозитория: + +```bash +bash deploy/scripts/test_t2_server.sh +bash deploy/scripts/test_t2_ui.sh +``` + +Для production перед этими командами обязательно обновить `deploy/backup/archive/`. diff --git a/deploy/SETUP_TURN_SERVER.md b/deploy/SETUP_TURN_SERVER.md new file mode 100644 index 00000000..cb2d291f --- /dev/null +++ b/deploy/SETUP_TURN_SERVER.md @@ -0,0 +1,85 @@ +# Настройка TURN-сервера + +TURN-хосты SHiNE должны использовать домены: + +- `turn1.shineup.me` +- `turn2.shineup.me` +- `turn3.shineup.me` + +IP не фиксировать в документах и скриптах как основной идентификатор. + +## 1. DNS + +Создать или обновить DNS `A/AAAA` для нужного `turnX.shineup.me`. + +## 2. Пакеты + +```bash +sudo apt update +sudo apt install -y coturn caddy +``` + +Можно использовать вспомогательный скрипт на самом TURN-хосте: + +```bash +sudo bash deploy/scripts/setup_turn_coturn.sh --realm turn1.shineup.me --secret CHANGE_ME_LONG_RANDOM_SECRET +``` + +## 3. coturn + +Секреты не хранить в git. Настраивать на сервере через `/etc/turnserver.conf` или отдельный secret/override. + +Минимальная схема: + +```conf +listening-port=3478 +tls-listening-port=5349 +fingerprint +lt-cred-mech +realm=turn1.shineup.me +server-name=turn1.shineup.me +use-auth-secret +static-auth-secret= +no-multicast-peers +no-cli +``` + +Включить сервис: + +```bash +sudo systemctl enable coturn +sudo systemctl restart coturn +``` + +## 4. Caddy + +Caddy можно использовать для HTTPS health/check endpoint и автоматического TLS на домене. + +Пример: + +```caddyfile +turn1.shineup.me { + respond /health "ok" 200 +} +``` + +Проверка: + +```bash +sudo caddy validate --config /etc/caddy/Caddyfile +sudo systemctl restart caddy +curl -I https://turn1.shineup.me/health +``` + +## 5. Проверка портов + +```bash +sudo systemctl --no-pager --full status coturn caddy +sudo ss -lntup | grep -E ':(3478|5349)' +``` + +## 6. Важное + +- TURN credentials и shared secret не коммитить. +- Если TURN домен переносится на другой VPS, менять DNS, а не код приложения. +- После изменения TURN-адресов обновить серверные/UI настройки, где они используются. diff --git a/deploy/TEST_SERVERS.md b/deploy/TEST_SERVERS.md new file mode 100644 index 00000000..95af47d1 --- /dev/null +++ b/deploy/TEST_SERVERS.md @@ -0,0 +1,61 @@ +# Test/devnet серверы SHiNE + +Отдельный test/devnet стенд состоит из четырёх независимых SHiNE-инстансов: + +- `t1.shineup.me` +- `t2.shineup.me` +- `t3.shineup.me` +- `t4.shineup.me` + +Это не production. Все deploy-цели задаются через домены. + +## Общие параметры + +- SSH: `player@tX.shineup.me` +- Solana cluster: `devnet` +- Solana RPC: `https://api.devnet.solana.com` +- Caddy config: `/etc/caddy/Caddyfile` + +## Инстансы + +| Домен | Логин сервера | Сервер | UI | Порт | systemd | +|---|---|---|---|---|---| +| `t1.shineup.me` | `server_t1` | `/home/player/t1/server` | `/home/player/t1/UI` | `7101` | `shine-t1.service` | +| `t2.shineup.me` | `server_t2` | `/home/player/t2/server` | `/home/player/t2/UI` | `7102` | `shine-t2.service` | +| `t3.shineup.me` | `server_t3` | `/home/player/t3/server` | `/home/player/t3/UI` | `7103` | `shine-t3.service` | +| `t4.shineup.me` | `server_t4` | `/home/player/t4/server` | `/home/player/t4/UI` | `7104` | `shine-t4.service` | + +## Deploy + +```bash +bash deploy/scripts/test_t1_server.sh +bash deploy/scripts/test_t1_ui.sh + +bash deploy/scripts/test_t2_server.sh +bash deploy/scripts/test_t2_ui.sh + +bash deploy/scripts/test_t3_server.sh +bash deploy/scripts/test_t3_ui.sh + +bash deploy/scripts/test_t4_server.sh +bash deploy/scripts/test_t4_ui.sh +``` + +## Проверка + +```bash +curl -I https://t1.shineup.me +curl -I https://t2.shineup.me +curl -I https://t3.shineup.me +curl -I https://t4.shineup.me +``` + +На сервере: + +```bash +sudo systemctl --no-pager --full status caddy shine-t1 shine-t2 shine-t3 shine-t4 +``` + +## Operational-нюанс + +Официальный `https://api.devnet.solana.com` может отдавать `HTTP 429`, если несколько инстансов одновременно делают bootstrap PDA/sync-серверов. Если после деплоя какой-то инстанс не подтянул `sync_servers`, рестартовать сервисы по одному с паузой. diff --git a/deploy/TURN_SERVERS.md b/deploy/TURN_SERVERS.md new file mode 100644 index 00000000..3107cb69 --- /dev/null +++ b/deploy/TURN_SERVERS.md @@ -0,0 +1,40 @@ +# TURN-серверы SHiNE + +TURN-серверы использовать и документировать через домены, а не через IP. + +## Текущие домены + +- `turn1.shineup.me` +- `turn2.shineup.me` +- `turn3.shineup.me` + +## Назначение + +TURN нужен для WebRTC-звонков, когда прямое peer-to-peer соединение невозможно из-за NAT/firewall. + +## Базовые ожидания + +- DNS каждого `turnX.shineup.me` указывает на актуальный физический сервер TURN. +- TLS/HTTPS и вспомогательная маршрутизация обслуживаются через Caddy, если на сервере есть web endpoint для проверки. +- `coturn` слушает TURN/STUN порты согласно локальному `turnserver.conf`. +- Секреты TURN не хранить в git. + +## Что проверять + +```bash +dig +short turn1.shineup.me +dig +short turn2.shineup.me +dig +short turn3.shineup.me +``` + +На каждом TURN-хосте: + +```bash +sudo systemctl --no-pager --full status coturn caddy +sudo ss -lntup | grep -E ':(3478|5349)' +``` + +## Где настраивать + +- TURN-хост с нуля: `SETUP_TURN_SERVER.md`. +- Подключение TURN к SHiNE backend: `CONFIGURE_TURN_IN_SHINE.md`. diff --git a/server-backup/AGENTS.md b/deploy/backup/AGENTS.md similarity index 63% rename from server-backup/AGENTS.md rename to deploy/backup/AGENTS.md index 5ecf1863..7d01fb60 100644 --- a/server-backup/AGENTS.md +++ b/deploy/backup/AGENTS.md @@ -1,7 +1,7 @@ -# AGENTS для server-backup +# AGENTS для deploy/backup ## Назначение -- Папка `server-backup/` хранит: +- Папка `deploy/backup/` хранит: - тяжёлые локальные бэкапы сервера (НЕ в git); - лёгкую схему восстановления (в git), чтобы можно было поднять сервер даже без полного архива. @@ -11,19 +11,20 @@ - `backup-version.properties` — версия контура бэкапа. ## Правила -- Полный бэкап складывать только в `server-backup/archive/`. -- `server-backup/archive/**` не коммитить. +- Полный бэкап складывать только в `deploy/backup/archive/`. +- `deploy/backup/archive/**` не коммитить, кроме `.gitkeep`. +- Перед production deploy проверить, что свежий бэкап скопирован в `deploy/backup/archive/<дата>/` и есть `MANIFEST.txt`. - Любое изменение схемы восстановления фиксировать в git. - После обновления схемы увеличивать `backup.schema.version`. - После нового полного бэкапа увеличивать `backup.full.version`. ## Как обновлять бэкап 1. Обновить схему: - - `bash server-backup/scheme/shineup.me/scripts/refresh_scheme.sh` + - `bash deploy/backup/scheme/shineup.me/scripts/refresh_scheme.sh` 2. Сделать новый полный бэкап: - - `bash server-backup/scheme/shineup.me/scripts/backup_full.sh` -3. Проверить `server-backup/archive/<дата>/MANIFEST.txt`. -4. Поднять версии в `server-backup/backup-version.properties`. + - `bash deploy/backup/scheme/shineup.me/scripts/backup_full.sh` +3. Проверить `deploy/backup/archive/<дата>/MANIFEST.txt`. +4. Поднять версии в `deploy/backup/backup-version.properties`. ## Как восстанавливать -- Смотреть `server-backup/scheme/shineup.me/docs/RESTORE.md`. +- Смотреть `deploy/backup/scheme/shineup.me/docs/RESTORE.md`. diff --git a/deploy/backup/README.md b/deploy/backup/README.md new file mode 100644 index 00000000..38a089df --- /dev/null +++ b/deploy/backup/README.md @@ -0,0 +1,9 @@ +# deploy/backup + +- `archive/` — локальные полные бэкапы по датам (не коммитятся, кроме `.gitkeep`). +- `scheme/` — лёгкая схема восстановления (коммитится). +- `backup-version.properties` — версии схемы и полного бэкапа. + +Production deploy требует, чтобы перед запуском свежий бэкап был скопирован в `deploy/backup/archive//` и содержал `MANIFEST.txt`. + +Основной сервер-источник: `shineup.me`. diff --git a/server-backup/archive/.gitkeep b/deploy/backup/archive/.gitkeep similarity index 100% rename from server-backup/archive/.gitkeep rename to deploy/backup/archive/.gitkeep diff --git a/server-backup/backup-version.properties b/deploy/backup/backup-version.properties similarity index 100% rename from server-backup/backup-version.properties rename to deploy/backup/backup-version.properties diff --git a/server-backup/scheme/shineup.me/captures/01_host_disk.txt b/deploy/backup/scheme/shineup.me/captures/01_host_disk.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/01_host_disk.txt rename to deploy/backup/scheme/shineup.me/captures/01_host_disk.txt diff --git a/server-backup/scheme/shineup.me/captures/02_enabled_services.txt b/deploy/backup/scheme/shineup.me/captures/02_enabled_services.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/02_enabled_services.txt rename to deploy/backup/scheme/shineup.me/captures/02_enabled_services.txt diff --git a/server-backup/scheme/shineup.me/captures/03_running_services.txt b/deploy/backup/scheme/shineup.me/captures/03_running_services.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/03_running_services.txt rename to deploy/backup/scheme/shineup.me/captures/03_running_services.txt diff --git a/server-backup/scheme/shineup.me/captures/04_listen_ports.txt b/deploy/backup/scheme/shineup.me/captures/04_listen_ports.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/04_listen_ports.txt rename to deploy/backup/scheme/shineup.me/captures/04_listen_ports.txt diff --git a/server-backup/scheme/shineup.me/captures/05_docker_ps.txt b/deploy/backup/scheme/shineup.me/captures/05_docker_ps.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/05_docker_ps.txt rename to deploy/backup/scheme/shineup.me/captures/05_docker_ps.txt diff --git a/server-backup/scheme/shineup.me/captures/06_home_player_sizes.txt b/deploy/backup/scheme/shineup.me/captures/06_home_player_sizes.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/06_home_player_sizes.txt rename to deploy/backup/scheme/shineup.me/captures/06_home_player_sizes.txt diff --git a/server-backup/scheme/shineup.me/captures/07_var_sizes.txt b/deploy/backup/scheme/shineup.me/captures/07_var_sizes.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/07_var_sizes.txt rename to deploy/backup/scheme/shineup.me/captures/07_var_sizes.txt diff --git a/server-backup/scheme/shineup.me/captures/UPDATED_AT_UTC.txt b/deploy/backup/scheme/shineup.me/captures/UPDATED_AT_UTC.txt similarity index 100% rename from server-backup/scheme/shineup.me/captures/UPDATED_AT_UTC.txt rename to deploy/backup/scheme/shineup.me/captures/UPDATED_AT_UTC.txt diff --git a/server-backup/scheme/shineup.me/configs/Caddyfile b/deploy/backup/scheme/shineup.me/configs/Caddyfile similarity index 100% rename from server-backup/scheme/shineup.me/configs/Caddyfile rename to deploy/backup/scheme/shineup.me/configs/Caddyfile diff --git a/server-backup/scheme/shineup.me/configs/systemd/agent-memory.service b/deploy/backup/scheme/shineup.me/configs/systemd/agent-memory.service similarity index 100% rename from server-backup/scheme/shineup.me/configs/systemd/agent-memory.service rename to deploy/backup/scheme/shineup.me/configs/systemd/agent-memory.service diff --git a/server-backup/scheme/shineup.me/configs/systemd/shine-server.service b/deploy/backup/scheme/shineup.me/configs/systemd/shine-server.service similarity index 100% rename from server-backup/scheme/shineup.me/configs/systemd/shine-server.service rename to deploy/backup/scheme/shineup.me/configs/systemd/shine-server.service diff --git a/server-backup/scheme/shineup.me/configs/turnserver.conf b/deploy/backup/scheme/shineup.me/configs/turnserver.conf similarity index 99% rename from server-backup/scheme/shineup.me/configs/turnserver.conf rename to deploy/backup/scheme/shineup.me/configs/turnserver.conf index 4d8d5cfb..4ef9e9f9 100644 --- a/server-backup/scheme/shineup.me/configs/turnserver.conf +++ b/deploy/backup/scheme/shineup.me/configs/turnserver.conf @@ -706,4 +706,4 @@ syslog #no-tlsv1 #no-tlsv1_1 #no-tlsv1_2 -static-auth-secret=def6d444734d380d2f67a9d345b1debf985eaba0973c343e392c060d97c30106 +static-auth-secret= diff --git a/server-backup/scheme/shineup.me/docs/RESTORE.md b/deploy/backup/scheme/shineup.me/docs/RESTORE.md similarity index 76% rename from server-backup/scheme/shineup.me/docs/RESTORE.md rename to deploy/backup/scheme/shineup.me/docs/RESTORE.md index 00613434..cfb2cd84 100644 --- a/server-backup/scheme/shineup.me/docs/RESTORE.md +++ b/deploy/backup/scheme/shineup.me/docs/RESTORE.md @@ -12,18 +12,18 @@ sudo apt install -y rsync caddy coturn docker.io ``` ## 3. Восстановление файлов из полного бэкапа -Предполагается, что полный бэкап лежит локально в `server-backup/archive/YYYY-MM-DD/`. +Предполагается, что полный бэкап лежит локально в `deploy/backup/archive/YYYY-MM-DD/`. ```bash -rsync -a server-backup/archive/YYYY-MM-DD/home-player/SHiNE/ player@NEW_SERVER:/home/player/SHiNE/ -rsync -a server-backup/archive/YYYY-MM-DD/home-player/sites/ player@NEW_SERVER:/home/player/sites/ -rsync -a server-backup/archive/YYYY-MM-DD/home-player/gitea/ player@NEW_SERVER:/home/player/gitea/ -rsync -a server-backup/archive/YYYY-MM-DD/home-player/agent-memory/ player@NEW_SERVER:/home/player/agent-memory/ +rsync -a deploy/backup/archive/YYYY-MM-DD/home-player/SHiNE/ player@NEW_SERVER:/home/player/SHiNE/ +rsync -a deploy/backup/archive/YYYY-MM-DD/home-player/sites/ player@NEW_SERVER:/home/player/sites/ +rsync -a deploy/backup/archive/YYYY-MM-DD/home-player/gitea/ player@NEW_SERVER:/home/player/gitea/ +rsync -a deploy/backup/archive/YYYY-MM-DD/home-player/agent-memory/ player@NEW_SERVER:/home/player/agent-memory/ -rsync -a server-backup/archive/YYYY-MM-DD/etc-system/caddy/ player@NEW_SERVER:/tmp/restore-caddy/ -rsync -a server-backup/archive/YYYY-MM-DD/var-lib/caddy/ player@NEW_SERVER:/tmp/restore-var-lib-caddy/ -rsync -a server-backup/archive/YYYY-MM-DD/etc-system/turnserver.conf player@NEW_SERVER:/tmp/turnserver.conf -rsync -a server-backup/archive/YYYY-MM-DD/etc-system/*.service player@NEW_SERVER:/tmp/ +rsync -a deploy/backup/archive/YYYY-MM-DD/etc-system/caddy/ player@NEW_SERVER:/tmp/restore-caddy/ +rsync -a deploy/backup/archive/YYYY-MM-DD/var-lib/caddy/ player@NEW_SERVER:/tmp/restore-var-lib-caddy/ +rsync -a deploy/backup/archive/YYYY-MM-DD/etc-system/turnserver.conf player@NEW_SERVER:/tmp/turnserver.conf +rsync -a deploy/backup/archive/YYYY-MM-DD/etc-system/*.service player@NEW_SERVER:/tmp/ ``` Далее на новом сервере: diff --git a/server-backup/scheme/shineup.me/scripts/backup_full.sh b/deploy/backup/scheme/shineup.me/scripts/backup_full.sh similarity index 100% rename from server-backup/scheme/shineup.me/scripts/backup_full.sh rename to deploy/backup/scheme/shineup.me/scripts/backup_full.sh diff --git a/server-backup/scheme/shineup.me/scripts/refresh_scheme.sh b/deploy/backup/scheme/shineup.me/scripts/refresh_scheme.sh similarity index 100% rename from server-backup/scheme/shineup.me/scripts/refresh_scheme.sh rename to deploy/backup/scheme/shineup.me/scripts/refresh_scheme.sh diff --git a/deploy/scripts/deploy_server.sh b/deploy/scripts/deploy_server.sh new file mode 100755 index 00000000..e3647e03 --- /dev/null +++ b/deploy/scripts/deploy_server.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" + +REMOTE_HOST="${REMOTE_HOST:?REMOTE_HOST is required, example: player@shineup.me}" +TARGET_DOMAIN="${TARGET_DOMAIN:?TARGET_DOMAIN is required, example: shineup.me}" +REMOTE_SERVER_DIR="${REMOTE_SERVER_DIR:?REMOTE_SERVER_DIR is required}" +REMOTE_LOGS_DIR="${REMOTE_LOGS_DIR:-$REMOTE_SERVER_DIR/logs}" +REMOTE_DATA_DIR="${REMOTE_DATA_DIR:-$REMOTE_SERVER_DIR/data}" +REMOTE_SERVICE_NAME="${REMOTE_SERVICE_NAME:?REMOTE_SERVICE_NAME is required}" +SERVER_PORT="${SERVER_PORT:?SERVER_PORT is required}" +LOCAL_JAR="${LOCAL_JAR:-$ROOT_DIR/SHiNE-server/build/libs/shine-server.jar}" +BUILD_JAR="${BUILD_JAR:-1}" +REQUIRE_BACKUP="${REQUIRE_BACKUP:-0}" +BACKUP_DIR="${BACKUP_DIR:-$ROOT_DIR/deploy/backup/archive}" + +if [[ "$REQUIRE_BACKUP" == "1" ]]; then + if ! find "$BACKUP_DIR" -mindepth 2 -maxdepth 2 -name MANIFEST.txt -print -quit 2>/dev/null | grep -q .; then + echo "ERROR: для production deploy сначала положите свежий бэкап в $BACKUP_DIR//MANIFEST.txt" >&2 + exit 1 + fi +fi + +if [[ "$BUILD_JAR" == "1" ]]; then + echo "==> Building server jar" + (cd "$ROOT_DIR" && ./gradlew shadowJar) +fi + +if [[ ! -f "$LOCAL_JAR" ]]; then + echo "ERROR: локальный jar не найден: $LOCAL_JAR" >&2 + exit 1 +fi + +echo "==> Deploy server to $TARGET_DOMAIN ($REMOTE_HOST)" +ssh -o BatchMode=yes -o ConnectTimeout=20 "$REMOTE_HOST" "echo SSH OK" >/dev/null +ssh "$REMOTE_HOST" "sudo -n true" +ssh "$REMOTE_HOST" "java -version >/dev/null 2>&1" + +TMP_DIR="$(mktemp -d)" +cleanup() { + rm -rf "$TMP_DIR" +} +trap cleanup EXIT + +cat >"$TMP_DIR/$REMOTE_SERVICE_NAME.service" </dev/null" + +echo "Всё хорошо: сервер $TARGET_DOMAIN обновлён и сервис $REMOTE_SERVICE_NAME перезапущен" diff --git a/deploy_shine-PWA.sh b/deploy/scripts/deploy_ui.sh similarity index 81% rename from deploy_shine-PWA.sh rename to deploy/scripts/deploy_ui.sh index c63dd683..f1924068 100755 --- a/deploy_shine-PWA.sh +++ b/deploy/scripts/deploy_ui.sh @@ -1,16 +1,32 @@ #!/usr/bin/env bash set -euo pipefail -SRC_DIR="shine-UI" -REMOTE_HOST="${REMOTE_HOST:-player@shineup.me}" -REMOTE_UI_DIR="${REMOTE_UI_DIR:-/home/player/SHiNE/shine-ui}" -EXPECTED_CADDY_UI_ROOT="${EXPECTED_CADDY_UI_ROOT:-/home/player/SHiNE/shine-ui}" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" + +SRC_DIR="$ROOT_DIR/shine-UI" +REMOTE_HOST="${REMOTE_HOST:?REMOTE_HOST is required, example: player@shineup.me}" +REMOTE_UI_DIR="${REMOTE_UI_DIR:?REMOTE_UI_DIR is required}" +EXPECTED_CADDY_UI_ROOT="${EXPECTED_CADDY_UI_ROOT:-$REMOTE_UI_DIR}" ALLOW_CADDY_MISMATCH="${ALLOW_CADDY_MISMATCH:-0}" -EXPECTED_CADDY_SITE="${EXPECTED_CADDY_SITE:-shineup.me}" +EXPECTED_CADDY_SITE="${EXPECTED_CADDY_SITE:?EXPECTED_CADDY_SITE is required}" +TARGET_URL="${TARGET_URL:-https://${EXPECTED_CADDY_SITE}}" +DEPLOY_SERVER_LOGIN="${DEPLOY_SERVER_LOGIN:-}" +DEPLOY_SERVER_ADDRESS="${DEPLOY_SERVER_ADDRESS:-}" +DEPLOY_SOLANA_CLUSTER="${DEPLOY_SOLANA_CLUSTER:-}" +DEPLOY_SOLANA_ENDPOINT="${DEPLOY_SOLANA_ENDPOINT:-}" +REQUIRE_BACKUP="${REQUIRE_BACKUP:-0}" +BACKUP_DIR="${BACKUP_DIR:-$ROOT_DIR/deploy/backup/archive}" +VERSION_FILE="$ROOT_DIR/VERSION.properties" BUILD_VERSION="$(date -u +%Y%m%d%H%M%S)" -VERSION_FILE="VERSION.properties" export BUILD_VERSION -TMP_DIR="$(mktemp -d)" + +if [[ "$REQUIRE_BACKUP" == "1" ]]; then + if ! find "$BACKUP_DIR" -mindepth 2 -maxdepth 2 -name MANIFEST.txt -print -quit 2>/dev/null | grep -q .; then + echo "ERROR: для production deploy сначала положите свежий бэкап в $BACKUP_DIR//MANIFEST.txt" >&2 + exit 1 + fi +fi if [[ ! -f "$VERSION_FILE" ]]; then echo "ERROR: version file not found: $VERSION_FILE" >&2 @@ -24,18 +40,12 @@ if [[ -z "$CLIENT_VERSION" ]]; then fi export CLIENT_VERSION -TARGET_URL="${TARGET_URL:-https://${EXPECTED_CADDY_SITE}}" -REMOTE_DIR="${REMOTE_UI_DIR}" -DEPLOY_SERVER_LOGIN="${DEPLOY_SERVER_LOGIN:-}" -DEPLOY_SERVER_ADDRESS="${DEPLOY_SERVER_ADDRESS:-}" -DEPLOY_SOLANA_CLUSTER="${DEPLOY_SOLANA_CLUSTER:-}" -DEPLOY_SOLANA_ENDPOINT="${DEPLOY_SOLANA_ENDPOINT:-}" DEPLOY_SOLANA_CLUSTER_NORMALIZED="$DEPLOY_SOLANA_CLUSTER" - if [[ "$DEPLOY_SOLANA_CLUSTER_NORMALIZED" == "mainnet" ]]; then DEPLOY_SOLANA_CLUSTER_NORMALIZED="mainnet-beta" fi +TMP_DIR="$(mktemp -d)" cleanup() { rm -rf "$TMP_DIR" } @@ -48,7 +58,7 @@ fi echo "==> Preparing staged UI copy with build version: $BUILD_VERSION" echo "==> Client version from $VERSION_FILE: $CLIENT_VERSION" -echo "==> Deploy target: $TARGET_URL ($REMOTE_DIR)" +echo "==> Deploy target: $TARGET_URL ($REMOTE_UI_DIR)" rsync -a "$SRC_DIR"/ "$TMP_DIR"/ DEPLOY_CONFIG_FILE="$TMP_DIR/js/deploy-config.js" @@ -156,12 +166,14 @@ elif [[ "$ROOT_CHECK_OUTPUT" != *"$EXPECTED_CADDY_UI_ROOT"* ]]; then echo "WARN: proceeding due to ALLOW_CADDY_MISMATCH=1" fi -echo "==> Preparing remote directory: $REMOTE_DIR" -ssh "$REMOTE_HOST" "sudo mkdir -p '$REMOTE_DIR'" +echo "==> Preparing remote directory: $REMOTE_UI_DIR" +ssh "$REMOTE_HOST" "sudo mkdir -p '$REMOTE_UI_DIR'" -echo "==> Syncing staged files to $REMOTE_DIR" +echo "==> Syncing staged files to $REMOTE_UI_DIR" rsync -rlvz --delete --omit-dir-times --no-perms --no-owner --no-group \ --rsync-path="sudo rsync" \ - "$TMP_DIR"/ "$REMOTE_HOST":"$REMOTE_DIR"/ + "$TMP_DIR"/ "$REMOTE_HOST":"$REMOTE_UI_DIR"/ + +ssh "$REMOTE_HOST" "sudo find '$REMOTE_UI_DIR' -type d -exec chmod o+rx {} +; sudo find '$REMOTE_UI_DIR' -type f -exec chmod o+r {} +" echo "Всё хорошо: $TARGET_URL" diff --git a/deploy/scripts/production_server2_server.sh b/deploy/scripts/production_server2_server.sh new file mode 100755 index 00000000..c3645c47 --- /dev/null +++ b/deploy/scripts/production_server2_server.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@server2.shineup.me" \ +TARGET_DOMAIN="server2.shineup.me" \ +REMOTE_SERVER_DIR="/home/player/SHiNE/shine-server" \ +REMOTE_SERVICE_NAME="shine-server" \ +SERVER_PORT="7070" \ +REQUIRE_BACKUP="1" \ +bash "$(dirname "$0")/deploy_server.sh" diff --git a/deploy/scripts/production_server2_ui.sh b/deploy/scripts/production_server2_ui.sh new file mode 100755 index 00000000..aa69af7f --- /dev/null +++ b/deploy/scripts/production_server2_ui.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@server2.shineup.me" \ +REMOTE_UI_DIR="/home/player/SHiNE/shine-ui" \ +EXPECTED_CADDY_UI_ROOT="/home/player/SHiNE/shine-ui" \ +EXPECTED_CADDY_SITE="server2.shineup.me" \ +DEPLOY_SERVER_LOGIN="server2shineupme" \ +DEPLOY_SERVER_ADDRESS="server2.shineup.me" \ +DEPLOY_SOLANA_CLUSTER="mainnet" \ +DEPLOY_SOLANA_ENDPOINT="https://solana-rpc.publicnode.com" \ +TARGET_URL="https://server2.shineup.me" \ +REQUIRE_BACKUP="1" \ +bash "$(dirname "$0")/deploy_ui.sh" diff --git a/deploy/scripts/production_shineupme_server.sh b/deploy/scripts/production_shineupme_server.sh new file mode 100755 index 00000000..5b7c554b --- /dev/null +++ b/deploy/scripts/production_shineupme_server.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@shineup.me" \ +TARGET_DOMAIN="shineup.me" \ +REMOTE_SERVER_DIR="/home/player/SHiNE/shine-server" \ +REMOTE_SERVICE_NAME="shine-server" \ +SERVER_PORT="7070" \ +REQUIRE_BACKUP="1" \ +bash "$(dirname "$0")/deploy_server.sh" diff --git a/deploy_shine-ui_production_shineupme.sh b/deploy/scripts/production_shineupme_ui.sh old mode 100644 new mode 100755 similarity index 87% rename from deploy_shine-ui_production_shineupme.sh rename to deploy/scripts/production_shineupme_ui.sh index e61a55c7..37fc0474 --- a/deploy_shine-ui_production_shineupme.sh +++ b/deploy/scripts/production_shineupme_ui.sh @@ -10,4 +10,5 @@ DEPLOY_SERVER_ADDRESS="shineup.me" \ DEPLOY_SOLANA_CLUSTER="mainnet" \ DEPLOY_SOLANA_ENDPOINT="https://solana-rpc.publicnode.com" \ TARGET_URL="https://shineup.me" \ -bash "$(dirname "$0")/deploy_shine-PWA.sh" +REQUIRE_BACKUP="1" \ +bash "$(dirname "$0")/deploy_ui.sh" diff --git a/scripts/setup_turn_coturn.sh b/deploy/scripts/setup_turn_coturn.sh similarity index 81% rename from scripts/setup_turn_coturn.sh rename to deploy/scripts/setup_turn_coturn.sh index 5a98944e..20494924 100755 --- a/scripts/setup_turn_coturn.sh +++ b/deploy/scripts/setup_turn_coturn.sh @@ -5,10 +5,10 @@ set -euo pipefail # Запускать НА TURN-сервере под root. # # Пример: -# sudo bash scripts/setup_turn_coturn.sh --secret "CHANGE_ME_LONG_SECRET" --realm "shineup.me" +# sudo bash deploy/scripts/setup_turn_coturn.sh --secret "CHANGE_ME_LONG_SECRET" --realm "turn1.shineup.me" SECRET="" -REALM="shineup.me" +REALM="turn1.shineup.me" MIN_PORT="49160" MAX_PORT="49200" @@ -46,9 +46,12 @@ export DEBIAN_FRONTEND=noninteractive apt-get update -y apt-get install -y coturn -PUBLIC_IP="$(hostname -I | awk '{print $1}')" +PUBLIC_IP="$(getent ahostsv4 "$REALM" | awk '{print $1; exit}')" if [[ -z "${PUBLIC_IP}" ]]; then - echo "Не удалось определить public ip автоматически, укажите вручную в /etc/turnserver.conf" >&2 + PUBLIC_IP="$(hostname -I | awk '{print $1}')" +fi +if [[ -z "${PUBLIC_IP}" ]]; then + echo "Не удалось определить public ip автоматически по домену ${REALM}, укажите вручную в /etc/turnserver.conf" >&2 PUBLIC_IP="0.0.0.0" fi diff --git a/deploy/scripts/test_t1_server.sh b/deploy/scripts/test_t1_server.sh new file mode 100755 index 00000000..f38fbdf8 --- /dev/null +++ b/deploy/scripts/test_t1_server.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@t1.shineup.me" \ +TARGET_DOMAIN="t1.shineup.me" \ +REMOTE_SERVER_DIR="/home/player/t1/server" \ +REMOTE_SERVICE_NAME="shine-t1" \ +SERVER_PORT="7101" \ +bash "$(dirname "$0")/deploy_server.sh" diff --git a/deploy_shine-ui_t1.sh b/deploy/scripts/test_t1_ui.sh old mode 100644 new mode 100755 similarity index 81% rename from deploy_shine-ui_t1.sh rename to deploy/scripts/test_t1_ui.sh index bd09bb5d..c097b1fc --- a/deploy_shine-ui_t1.sh +++ b/deploy/scripts/test_t1_ui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -REMOTE_HOST="player@178.208.90.249" \ +REMOTE_HOST="player@t1.shineup.me" \ REMOTE_UI_DIR="/home/player/t1/UI" \ EXPECTED_CADDY_UI_ROOT="/home/player/t1/UI" \ EXPECTED_CADDY_SITE="t1.shineup.me" \ @@ -10,4 +10,4 @@ DEPLOY_SERVER_ADDRESS="t1.shineup.me" \ DEPLOY_SOLANA_CLUSTER="devnet" \ DEPLOY_SOLANA_ENDPOINT="https://api.devnet.solana.com" \ TARGET_URL="https://t1.shineup.me" \ -bash "$(dirname "$0")/deploy_shine-PWA.sh" +bash "$(dirname "$0")/deploy_ui.sh" diff --git a/deploy/scripts/test_t2_server.sh b/deploy/scripts/test_t2_server.sh new file mode 100755 index 00000000..1a34c459 --- /dev/null +++ b/deploy/scripts/test_t2_server.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@t2.shineup.me" \ +TARGET_DOMAIN="t2.shineup.me" \ +REMOTE_SERVER_DIR="/home/player/t2/server" \ +REMOTE_SERVICE_NAME="shine-t2" \ +SERVER_PORT="7102" \ +bash "$(dirname "$0")/deploy_server.sh" diff --git a/deploy_shine-ui_t2.sh b/deploy/scripts/test_t2_ui.sh old mode 100644 new mode 100755 similarity index 81% rename from deploy_shine-ui_t2.sh rename to deploy/scripts/test_t2_ui.sh index 443ce206..fbeeaf61 --- a/deploy_shine-ui_t2.sh +++ b/deploy/scripts/test_t2_ui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -REMOTE_HOST="player@178.208.90.249" \ +REMOTE_HOST="player@t2.shineup.me" \ REMOTE_UI_DIR="/home/player/t2/UI" \ EXPECTED_CADDY_UI_ROOT="/home/player/t2/UI" \ EXPECTED_CADDY_SITE="t2.shineup.me" \ @@ -10,4 +10,4 @@ DEPLOY_SERVER_ADDRESS="t2.shineup.me" \ DEPLOY_SOLANA_CLUSTER="devnet" \ DEPLOY_SOLANA_ENDPOINT="https://api.devnet.solana.com" \ TARGET_URL="https://t2.shineup.me" \ -bash "$(dirname "$0")/deploy_shine-PWA.sh" +bash "$(dirname "$0")/deploy_ui.sh" diff --git a/deploy/scripts/test_t3_server.sh b/deploy/scripts/test_t3_server.sh new file mode 100755 index 00000000..68a609df --- /dev/null +++ b/deploy/scripts/test_t3_server.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@t3.shineup.me" \ +TARGET_DOMAIN="t3.shineup.me" \ +REMOTE_SERVER_DIR="/home/player/t3/server" \ +REMOTE_SERVICE_NAME="shine-t3" \ +SERVER_PORT="7103" \ +bash "$(dirname "$0")/deploy_server.sh" diff --git a/deploy_shine-ui_t3.sh b/deploy/scripts/test_t3_ui.sh old mode 100644 new mode 100755 similarity index 81% rename from deploy_shine-ui_t3.sh rename to deploy/scripts/test_t3_ui.sh index ff9d48dd..fd76ef8e --- a/deploy_shine-ui_t3.sh +++ b/deploy/scripts/test_t3_ui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -REMOTE_HOST="player@178.208.90.249" \ +REMOTE_HOST="player@t3.shineup.me" \ REMOTE_UI_DIR="/home/player/t3/UI" \ EXPECTED_CADDY_UI_ROOT="/home/player/t3/UI" \ EXPECTED_CADDY_SITE="t3.shineup.me" \ @@ -10,4 +10,4 @@ DEPLOY_SERVER_ADDRESS="t3.shineup.me" \ DEPLOY_SOLANA_CLUSTER="devnet" \ DEPLOY_SOLANA_ENDPOINT="https://api.devnet.solana.com" \ TARGET_URL="https://t3.shineup.me" \ -bash "$(dirname "$0")/deploy_shine-PWA.sh" +bash "$(dirname "$0")/deploy_ui.sh" diff --git a/deploy/scripts/test_t4_server.sh b/deploy/scripts/test_t4_server.sh new file mode 100755 index 00000000..5a4c6ba9 --- /dev/null +++ b/deploy/scripts/test_t4_server.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +REMOTE_HOST="player@t4.shineup.me" \ +TARGET_DOMAIN="t4.shineup.me" \ +REMOTE_SERVER_DIR="/home/player/t4/server" \ +REMOTE_SERVICE_NAME="shine-t4" \ +SERVER_PORT="7104" \ +bash "$(dirname "$0")/deploy_server.sh" diff --git a/deploy_shine-ui_t4.sh b/deploy/scripts/test_t4_ui.sh old mode 100644 new mode 100755 similarity index 81% rename from deploy_shine-ui_t4.sh rename to deploy/scripts/test_t4_ui.sh index 151d1971..415f1124 --- a/deploy_shine-ui_t4.sh +++ b/deploy/scripts/test_t4_ui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -REMOTE_HOST="player@178.208.90.249" \ +REMOTE_HOST="player@t4.shineup.me" \ REMOTE_UI_DIR="/home/player/t4/UI" \ EXPECTED_CADDY_UI_ROOT="/home/player/t4/UI" \ EXPECTED_CADDY_SITE="t4.shineup.me" \ @@ -10,4 +10,4 @@ DEPLOY_SERVER_ADDRESS="t4.shineup.me" \ DEPLOY_SOLANA_CLUSTER="devnet" \ DEPLOY_SOLANA_ENDPOINT="https://api.devnet.solana.com" \ TARGET_URL="https://t4.shineup.me" \ -bash "$(dirname "$0")/deploy_shine-PWA.sh" +bash "$(dirname "$0")/deploy_ui.sh" diff --git a/deploy_shine-server_server2shineupme.sh b/deploy_shine-server_server2shineupme.sh deleted file mode 100644 index b846ef2d..00000000 --- a/deploy_shine-server_server2shineupme.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -TARGET_HOST="${TARGET_HOST:-player@193.8.215.70}" -TARGET_DOMAIN="${TARGET_DOMAIN:-server2.shineup.me}" -REMOTE_BASE="${REMOTE_BASE:-/home/player/SHiNE}" -REMOTE_SERVER_DIR="${REMOTE_SERVER_DIR:-$REMOTE_BASE/shine-server}" -REMOTE_DATA_DIR="${REMOTE_DATA_DIR:-$REMOTE_SERVER_DIR/data}" -REMOTE_LOGS_DIR="${REMOTE_LOGS_DIR:-$REMOTE_SERVER_DIR/logs}" -REMOTE_UI_DIR="${REMOTE_UI_DIR:-$REMOTE_BASE/shine-ui}" -REMOTE_SERVICE_NAME="${REMOTE_SERVICE_NAME:-shine-server}" -LOCAL_JAR="${LOCAL_JAR:-SHiNE-server/build/libs/shine-server.jar}" - -TMP_DIR="$(mktemp -d)" -cleanup() { - rm -rf "$TMP_DIR" -} -trap cleanup EXIT - -if [[ ! -f "$LOCAL_JAR" ]]; then - echo "ERROR: локальный jar не найден: $LOCAL_JAR" >&2 - exit 1 -fi - -ssh -o BatchMode=yes -o ConnectTimeout=20 "$TARGET_HOST" "echo SSH OK" >/dev/null -ssh "$TARGET_HOST" "sudo -n true" -ssh "$TARGET_HOST" "java -version >/dev/null 2>&1" - -cat >"$TMP_DIR/shine-server.service" <` и отдельная автономная страница `shine-UI/promo-code-generator.html` для генерации promo-кода через браузерный кошелёк или через ручной ввод Base58 seed 32 bytes; -- что проверять: - - admin-транзакцией создать или обновить `promo_seller_pda`; - - сгенерировать promo-код на странице `promo-code-generator.html` в режиме wallet extension; - - сгенерировать promo-код на той же странице в режиме ручного Base58 seed; - - открыть HTML локально как отдельный файл без сервера и убедиться, что генерация в режиме Base58 seed продолжает работать; - - зарегистрировать короткий/premium логин по promo-коду; - - убедиться, что без promo-кода тот же логин не проходит `shine_login_guard`; - - убедиться, что после успешной регистрации `remaining_sales` уменьшается на 1; - - проверить отказ при исчерпанной квоте, неверной подписи и логине короче `min_login_length`; -- ожидаемый результат: - - promo-регистрация проходит только при валидной подписи продавца и соблюдении лимитов; - - обычная регистрация без promo-кода продолжает работать как раньше; - - страница генерации выдаёт строку формата `1seller-signatureBase58` в обоих режимах; - - single-file HTML работает локально оффлайн минимум в режиме ручного Base58 seed; -- статус: - - `pending` diff --git a/docs/Pending_Features/2026-07-01_1945_mainnet-solana-addresses-sync.md b/docs/Pending_Features/2026-07-01_1945_mainnet-solana-addresses-sync.md deleted file mode 100644 index d309652f..00000000 --- a/docs/Pending_Features/2026-07-01_1945_mainnet-solana-addresses-sync.md +++ /dev/null @@ -1,51 +0,0 @@ -# Синхронизация mainnet-адресов Solana по UI/серверу/ESP32 - -- статус: `pending` - -## Кратко - -Во все основные клиентские и серверные точки проекта протянуты актуальные mainnet-адреса программ: - -- `shine_login_guard`: `SHiGxGsXGioQYCYhchQ5R7KWoxN5UjFAFsucPf6sfnh` -- `shine_users`: `SHiNEPr1APdAgNBteUyBXcNovaHctpSjUu8oH2ZJdN6` -- `shine_payments`: `SHiPmXbM9Fs9khzRUW3TGKsS2W84aqaXTxs3ZkajW9v` - -Также по умолчанию переключены основные RPC defaults на `https://api.mainnet-beta.solana.com` там, где это нужно для рабочего mainnet-сценария. - -## Что проверять - -1. Основной UI: - - отображение и использование новых program id; - - регистрация/чтение Solana PDA в mainnet; - - экран кошелька и покупка лимита. - -2. Server UI: - - создание server PDA в mainnet; - - чтение PDA; - - обновление PDA; - - корректная блокировка devnet-автопополнения при mainnet endpoint. - -3. Browser plugin wallet: - - резолв `user_pda` и `server PDA` через mainnet RPC. - -4. Web UI `shine_payments`: - - чтение очередей; - - покупка билета; - - admin/manager/dao tools открываются с новыми program id и mainnet RPC. - -5. ESP32 homeserver UI: - - отображаются новые program id; - - дефолтный Solana RPC теперь mainnet. - -6. Временный режим регистрации: - - в основном UI логины длиной 5-7 символов без временного кода не проходят; - - в основном UI логины длиной 5-7 символов с временным кодом проходят локальную проверку; - - в основном UI любой другой временный код отклоняется сразу; - - ESP32 и прямой on-chain вызов `shine_users` полагаются на текущий временный `shine_login_guard`, то есть валидные логины длиной от 5 символов допускаются без словарной классификации. - -## Ожидаемый результат - -- Во всех перечисленных поверхностях используются новые mainnet program id. -- Запросы по умолчанию идут в mainnet, кроме явно devnet-утилит. -- Нет обращений к старым devnet program id. -- Временный UI-барьер для коротких логинов работает так, как задумано, и не ломает обычную регистрацию для логинов от 8 символов. diff --git a/docs/Pending_Features/2026-07-01_2135_временный_режим_коротких_логинов.md b/docs/Pending_Features/2026-07-01_2135_временный_режим_коротких_логинов.md deleted file mode 100644 index 71e5a523..00000000 --- a/docs/Pending_Features/2026-07-01_2135_временный_режим_коротких_логинов.md +++ /dev/null @@ -1,42 +0,0 @@ -# Временный режим коротких логинов - -- статус: `pending` - -## Кратко - -Временно упрощён `shine_login_guard`: - -- on-chain допускаются любые валидные логины длиной от `5` символов; -- словарная premium/trademark-классификация временно отключена. - -Поверх этого основной UI вводит временное ограничение: - -- логины длиной `8+` проходят обычную проверку; -- логины длиной `5..7` допускаются только при вводе временного кода; -- любой другой код отклоняется сразу. - -ESP32 в этом временном режиме не ограничивается UI-кодом и использует только on-chain правила. - -## Что проверять - -1. Основной UI: - - логин длиной `4` символа отклоняется; - - логин длиной `5..7` без временного кода отклоняется; - - логин длиной `5..7` с корректным временным кодом проходит локальную проверку; - - логин длиной `5..7` с любым другим кодом отклоняется; - - логин длиной `8+` проходит без временного кода. - -2. Solana on-chain: - - `shine_login_guard` возвращает `CLASS_FREE` для валидных логинов длиной от `5`; - - `shine_login_guard` возвращает `CLASS_PREMIUM` для логинов короче `5` или с невалидными символами. - -3. ESP32 / прямой вызов: - - валидный логин длиной `5+` регистрируется без временного кода; - - логин короче `5` не регистрируется. - -## Ожидаемый результат - -- Основной UI удерживает обычных пользователей от коротких логинов без временного кода. -- Свои пользователи могут временно регистрировать короткие логины через UI-код. -- ESP32 продолжает работать без отдельной промо-логики. -- On-chain логика остаётся простой и компактной. diff --git a/docs/Pending_Features/2026-07-09_0815_4_test_servers_devnet_vps.md b/docs/Pending_Features/2026-07-09_0815_4_test_servers_devnet_vps.md deleted file mode 100644 index 623ef4cc..00000000 --- a/docs/Pending_Features/2026-07-09_0815_4_test_servers_devnet_vps.md +++ /dev/null @@ -1,39 +0,0 @@ -# 4 тестовых SHiNE-сервера на одном VPS (`178.208.90.249`) - -- статус: `pending` - -## Кратко - -Поднят отдельный тестовый стенд: -- `t1.shineup.me` -- `t2.shineup.me` -- `t3.shineup.me` -- `t4.shineup.me` - -Каждый домен ведёт на свой SHiNE-инстанс под пользователем `player`, все инстансы работают через Solana `devnet`. - -## Что проверять - -- UI каждого домена открывается без ошибок: - - `https://t1.shineup.me` - - `https://t2.shineup.me` - - `https://t3.shineup.me` - - `https://t4.shineup.me` -- регистрация/логин клиента может работать через каждый из этих серверов -- WebSocket-подключение реально идёт на свой инстанс, а не в соседний -- чтение PDA и server-ui формы по умолчанию используют `devnet` -- межсерверный sync после ручных тестов действительно использует `access_servers/sync_servers` -- не происходит путаницы данных между `t1/t2/t3/t4` - -## Ожидаемый результат - -- каждый домен работает независимо -- у каждого инстанса своя БД и свои локальные данные -- `Caddy` корректно проксирует `/ws` на `7101..7104` -- серверы не падают после старта -- если devnet RPC временно даёт `429`, последовательный рестарт по одному инстансу позволяет подтянуть `sync_servers` - -## Примечание - -Подробная схема размещения описана в: -- [docs/deploy/test-server/178.208.90.249_quad_devnet.md](/home/ai/work/SHiNE/SHiNE-server-sha256/docs/deploy/test-server/178.208.90.249_quad_devnet.md) diff --git a/docs/Pending_Features/2026-07-10_1248_call_summary_dm_from_initiator.md b/docs/Pending_Features/2026-07-10_1248_call_summary_dm_from_initiator.md deleted file mode 100644 index 2db1f749..00000000 --- a/docs/Pending_Features/2026-07-10_1248_call_summary_dm_from_initiator.md +++ /dev/null @@ -1,17 +0,0 @@ -# Итог звонка как DM от инициатора - -- краткое описание фичи: - Вместо локальных `call-tech` записей итог звонка теперь отправляется как обычное DM-сообщение только от стороны, которая инициировала звонок. - -- что именно проверять: - 1. Успешный звонок: после завершения инициатор отправляет в чат DM вида `Звонок: 37с` или `Звонок: 2м 14с`. - 2. Неуспешный звонок без ответа: инициатор отправляет `Звонил, но недозвонился: нет ответа`. - 3. Неуспешный звонок, когда у адресата нет доставленных сессий: инициатор отправляет `Звонил, но недозвонился: абонент не в сети`. - 4. Неуспешный звонок при проблеме соединения: инициатор отправляет `Звонил, но недозвонился: не удалось установить соединение`. - 5. Старые локальные `call-tech` bubble про итог звонка больше не появляются ни у инициатора, ни у принимающей стороны. - -- ожидаемый результат: - Итог звонка виден обеим сторонам как обычное DM-сообщение от инициатора, а локальные служебные записи про итог звонка больше не используются. - -- статус: - pending diff --git a/docs/Pending_Features/2026-07-10_1748_dm_opaque_body_and_decrypt_fallback.md b/docs/Pending_Features/2026-07-10_1748_dm_opaque_body_and_decrypt_fallback.md deleted file mode 100644 index 173118a0..00000000 --- a/docs/Pending_Features/2026-07-10_1748_dm_opaque_body_and_decrypt_fallback.md +++ /dev/null @@ -1,23 +0,0 @@ -## Краткое описание - -Сервер перестал валидировать внутреннюю crypto-структуру `body` у контентных DM `type=1/2`. -UI теперь не отбрасывает такие сообщения: если сообщение не удалось расшифровать, вместо текста показывается заглушка `Неудалось расшифровать сообщение`. - -## Что проверять - -- Отправка и приём обычных DM между штатными клиентами продолжают работать как раньше. -- Сообщение с незнакомым форматом `body` у `type=1/2` принимается сервером и доходит до клиента. -- В UI такое сообщение отображается в чате одной из ожидаемых заглушек: - - `Формат сообщения не поддерживается` - - `Не удалось расшифровать сообщение` - - `Сообщение повреждено` -- После выхода из аккаунта и повторного входа backlog с такими сообщениями тоже отображается с той же заглушкой. -- ACK доставки по сессии для такого сообщения не зацикливается и сообщение не приходит бесконечно повторно. - -## Ожидаемый результат - -Сервер выступает транспортом для opaque DM-body, а клиент при неудачной расшифровке показывает безопасный fallback вместо полного пропуска сообщения с различением основных причин. - -## Статус - -pending diff --git a/docs/Pending_Features/2026-07-10_1845_dm_shine_tags_and_safe_preview.md b/docs/Pending_Features/2026-07-10_1845_dm_shine_tags_and_safe_preview.md deleted file mode 100644 index 98d897c2..00000000 --- a/docs/Pending_Features/2026-07-10_1845_dm_shine_tags_and_safe_preview.md +++ /dev/null @@ -1,28 +0,0 @@ -## Краткое описание - -В DM добавлен клиентский формат технических вставок в начале plaintext: - -- `` -- `` - -UI скрывает такие вставки из текста сообщения, а call-вставки отображает специальным человекочитаемым видом. -Также добавлена защита от пользовательского текста, начинающегося с `` показывается в чате как специальное call-сообщение, а не как сырой техтекст. -- При исходящем звонке короче `5` секунд call-summary не отправляется вообще. -- В списке личных сообщений превью такого сообщения показывает человекочитаемый итог звонка. -- DM с `Текст ответа` скрывает техблок и показывает только `Текст ответа`. -- В меню любого DM первым пунктом есть `Ответить`, и отправка из этого режима реально добавляет `` в начало plaintext. -- Если reply-цель отсутствует, сообщение всё равно показывается как обычный текст ответа. -- Текст вида `` или похожие HTML-теги не исполняются ни в чате, ни в списке личных сообщений, ни в списке каналов. - -## Ожидаемый результат - -Технические SHiNE-вставки работают только как управляющие метаданные UI, а отображаемый пользователю текст и превью остаются безопасными и не рендерят HTML. - -## Статус - -pending diff --git a/docs/Pending_Features/2026-07-14_1325_fix_call_remote_hangup_and_ack_timeout.md b/docs/Pending_Features/2026-07-14_1325_fix_call_remote_hangup_and_ack_timeout.md deleted file mode 100644 index d81fe498..00000000 --- a/docs/Pending_Features/2026-07-14_1325_fix_call_remote_hangup_and_ack_timeout.md +++ /dev/null @@ -1,30 +0,0 @@ -# Исправление завершения звонка и таймаутов ACK - -## Краткое описание - -Исправлена клиентская логика звонков: -- входящий экран теперь должен закрываться сразу при `remote_hangup`; -- после нажатия `Ответить` добавлен таймаут ожидания стадии `connecting`, чтобы окно не висело бесконечно; -- исходящий таймаут ожидания ACK больше не обрывает звонок слишком рано, если invite уже был доставлен. -- в локальный app log клиента добавлен точный timeline по этапам звонка: invite, выбор remoteSessionId, accept/offer/answer, ICE, смены `RTCPeerConnection` и финализация. -- добавлена явная диагностика `SESSION_NOT_FOUND` для звонковых сигналов: отдельный timeline-этап в клиенте и отдельный серверный warn-лог. - -## Что проверять - -- Если исходящая сторона завершила звонок, входящее окно у второй стороны закрывается сразу. -- Если принять входящий звонок, а соединение/offer не приходит, экран не висит бесконечно и сам завершается по таймауту. -- Если invite был доставлен, исходящий звонок не падает через 10 секунд раньше времени только из-за медленного ACK. -- В app log по звонку видна последовательность этапов с локальными `+N ms`, по которой можно понять, где именно образуется задержка или гонка. -- Если сигнал звонка не дошёл до целевой сессии, это явно видно и в клиенте, и в серверном логе. - -## Ожидаемый результат - -- Нет бесконечно висящего окна `Соединяем…` на принимающей стороне. -- В логах вместо преждевременного `no_ack_10s` для уже доставленного invite появляется более поздний таймаут. -- При `remote_hangup` звонок визуально завершается сразу. -- По каждому проблемному звонку есть локальный timeline и тот же краткий timeline попадает в `CallDeliveryReport`. -- В серверных логах есть строка `CALL_SIGNAL_SESSION_NOT_FOUND ...` с `callId`, `targetSessionId` и количеством активных сессий адресата. - -## Статус - -`pending` diff --git a/docs/Pending_Features/2026-07-14_1745_адаптация-шапки-связей.md b/docs/Pending_Features/2026-07-14_1745_адаптация-шапки-связей.md deleted file mode 100644 index 2bf2f6f8..00000000 --- a/docs/Pending_Features/2026-07-14_1745_адаптация-шапки-связей.md +++ /dev/null @@ -1,16 +0,0 @@ -# Адаптация верхней панели экрана «Связи» - -## Краткое описание -- Экран графа связей больше не расширяется за границы контейнера. Верхняя панель ограничена границами экрана, чтобы кнопки возврата, поиска и справки не обрезались на узких устройствах. - -## Что проверить -- Открыть экран «Связи» на ширине около 320, 390 и 794 px. -- Убедиться, что кнопки возврата, «Найти» и «?» полностью видны и нажимаются. -- Убедиться, что фильтры и граф связей остаются доступными. - -## Ожидаемый результат -- Верхние действия не выходят за левую или правую границу приложения. -- Заголовок при нехватке места сокращается, а не сдвигает кнопки за край. - -## Статус -- `pending` — локальная проверка на ширине 320 и 794 px пройдена; нужна ручная проверка после публикации на тестовом или production-стенде. diff --git a/docs/Pending_Features/2026-07-14_1830_кнопка-поиска-каналов.md b/docs/Pending_Features/2026-07-14_1830_кнопка-поиска-каналов.md deleted file mode 100644 index b96e6788..00000000 --- a/docs/Pending_Features/2026-07-14_1830_кнопка-поиска-каналов.md +++ /dev/null @@ -1,16 +0,0 @@ -# Кнопка поиска каналов - -## Краткое описание -- Emoji-иконка поиска в верхней панели «Каналов» заменена на контурную кнопку-лупу в стиле интерфейса. - -## Что проверить -- Открыть список каналов. -- Убедиться, что кнопка поиска видна рядом с кнопкой создания канала и имеет подсказку «Найти канал». -- Нажать кнопку и убедиться, что открывается прежнее окно поиска каналов. - -## Ожидаемый результат -- Кнопка выглядит как часть общей тёмной панели и не использует emoji. -- Поиск каналов работает без изменений. - -## Статус -- `pending` — локальная визуальная проверка и открытие окна поиска пройдены; нужна ручная проверка после публикации на тестовом или production-стенде. diff --git a/docs/Pending_Features/2026-07-14_1915_локальный-тестовый-вход.md b/docs/Pending_Features/2026-07-14_1915_локальный-тестовый-вход.md deleted file mode 100644 index 6a61be39..00000000 --- a/docs/Pending_Features/2026-07-14_1915_локальный-тестовый-вход.md +++ /dev/null @@ -1,20 +0,0 @@ -# Локальный тестовый вход - -## Краткое описание -- На `localhost`, `127.0.0.1` и `::1` доступна кнопка «Локальный тестовый вход». -- Она создаёт только локальный демо-сеанс `local-tester`; пароль, серверная сессия и production не используются. -- Экран личных сообщений и список каналов открывают автономные локальные состояния без запроса к серверу. -- Профиль заполняется демонстрационными данными, чтобы интерфейс можно было проверить без серверного пользователя. - -## Что проверить -- Открыть локальный UI и нажать «Локальный тестовый вход». -- Проверить переход к списку сообщений и доступ к экранам профиля, каналов, связей и настроек. -- Обновить страницу и убедиться, что локальный сеанс сохраняется. -- Выйти из сеанса и убедиться, что снова открывается экран старта. - -## Ожидаемый результат -- Локальный режим даёт возможность изучить интерфейс без реальной авторизации. -- На `shineup.me` и тестовых доменах кнопка отсутствует. - -## Статус -- `pending` — локальный вход, переход к профилю и демонстрационные каналы проверены; нужна ручная проверка выхода из сеанса после публикации на тестовом или production-стенде. diff --git a/docs/Pending_Features/2026-07-16_1935_проверка_public_solana_rpc_в_ui.md b/docs/Pending_Features/2026-07-16_1935_проверка_public_solana_rpc_в_ui.md deleted file mode 100644 index 6008e2a6..00000000 --- a/docs/Pending_Features/2026-07-16_1935_проверка_public_solana_rpc_в_ui.md +++ /dev/null @@ -1,23 +0,0 @@ -# Экран проверки public Solana RPC в UI - -- статус: `pending` - -## Кратко - -Добавлен отдельный экран разработчика для проверки публичных mainnet Solana RPC прямо из браузера. -Экран отправляет реальный JSON-RPC `getVersion` запрос к списку public endpoint-ов и показывает, -какие ноды реально подходят для browser use. - -## Что проверять - -- в `Настройки разработчика` появилась кнопка `Solana: проверить public RPC`; -- экран открывается без ошибок; -- по каждой mainnet ноде показывается итоговый статус; -- для доступных нод видно HTTP-статус, время ответа и версию `solana-core`; -- длинные URL и ошибки не распирают экран по ширине на телефоне. - -## Ожидаемый результат - -- можно визуально увидеть, какие public Solana RPC доступны именно из браузера; -- проверка работает без промежуточного сервера; -- экран остаётся mobile-first и не требует горизонтального скролла. diff --git a/docs/Pending_Features/2026-07-16_2035_ожидание_подтверждения_solana_при_регистрации.md b/docs/Pending_Features/2026-07-16_2035_ожидание_подтверждения_solana_при_регистрации.md deleted file mode 100644 index d546b671..00000000 --- a/docs/Pending_Features/2026-07-16_2035_ожидание_подтверждения_solana_при_регистрации.md +++ /dev/null @@ -1,20 +0,0 @@ -## Кратко -- Переделан финальный flow регистрации: сначала экран ожидания подтверждения Solana с прогрессом и повторными проверками, потом отдельный экран успешной регистрации с кнопкой входа в стандартный экран сохранения ключей. - -## Что проверять -- После отправки регистрации открывается экран ожидания с текстом про подтверждение Solana и кликабельным `Tx ID`. -- Прогресс-бар сначала идёт быстрее, потом заметно замедляется. -- Первая проверка регистрации начинается примерно через 4 секунды, далее повторяется раз в 2 секунды. -- Пока подтверждения нет, снизу показываются понятные статусы ожидания. -- После подтверждения открывается экран «Поздравляем с регистрацией» с одной кнопкой `Войти в аккаунт`. -- Кнопка `Войти в аккаунт` открывает штатный экран сохранения ключей с тремя галочками. -- Стрелка назад в левом верхнем углу на обоих экранах возвращает в главное меню. -- После успешного сохранения ключей регистрационный черновик и адрес кошелька очищаются. - -## Ожидаемый результат -- Пользователь не видит преждевременное поздравление до подтверждения регистрации в Solana. -- Финальный успех показывается только после появления подтверждения регистрации. -- Вход после регистрации идёт через тот же стандартный сценарий сохранения ключей, что и в обычном login-flow. - -## Статус -- pending diff --git a/docs/Pending_Features/README.md b/docs/Pending_Features/README.md deleted file mode 100644 index 071183a8..00000000 --- a/docs/Pending_Features/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Недопроверенные фичи - -Эта папка хранит список доработок, которые уже реализованы, но ещё не подтверждены ручной проверкой. - -## Как использовать - -1. При каждом коммите с новыми пользовательскими фичами (если нужна ручная проверка) добавить новый файл: - - формат: `YYYY-MM-DD_HHMM_.md` - - название `` и текст файла по возможности писать на русском языке -2. В файле указать: - - что сделано; - - как проверять; - - ожидаемый результат; - - текущий статус (`pending` / `in_progress` / `done`). -3. После подтверждения работоспособности — удалить файл фичи из этой папки. - -## Важно - -- `README.md` не удаляется. -- Количество недопроверенных фич = число файлов `*.md` в этой папке, кроме `README.md`. diff --git a/docs/Pending_Features/вроде сделанное/2026-06-20_1839_registration_faq_and_12_words.md b/docs/Pending_Features/вроде сделанное/2026-06-20_1839_registration_faq_and_12_words.md deleted file mode 100644 index 64ade24f..00000000 --- a/docs/Pending_Features/вроде сделанное/2026-06-20_1839_registration_faq_and_12_words.md +++ /dev/null @@ -1,25 +0,0 @@ -# Регистрация: FAQ и режим пароля из 12 слов - -- краткое описание: - - на экране регистрации добавлен блок частых вопросов с переходом на отдельный экран справки; - - добавлен альтернативный режим ввода пароля через 12 полей-слов в кошелёчном формате, которые склеиваются в одну строку без изменения API; - - такой же режим добавлен и на экран входа по логину и паролю. - -- что проверять: - - на стартовом экране открыть `Зарегистрироваться`; - - убедиться, что внизу экрана есть кнопки FAQ; - - открыть несколько вопросов и проверить возврат обратно на регистрацию; - - включить галочку `Представить пароль в виде 12 слов`; - - убедиться, что появляется сетка с нумерованными полями в 3 колонки; - - ввести часть слов, перейти дальше и проверить, что шаг подтверждения и генерация ключей работают; - - выключить галочку и проверить, что пароль остаётся собранным в одном поле; - - открыть экран входа по паролю и повторить те же проверки для режима `12 слов`; - - пройти регистрацию до шага оплаты без ошибок интерфейса. - -- ожидаемый результат: - - FAQ открывается отдельным экраном и содержит понятные ответы; - - режим `12 слов` не ломает регистрацию и вход и даёт тот же поток, что и обычный пароль; - - пароль не отправляется в новом формате, а продолжает использоваться как одна строка. - -- статус: - - pending diff --git a/docs/Pending_Features/вроде сделанное/2026-06-20_2350_test_free_avatar_upload.md b/docs/Pending_Features/вроде сделанное/2026-06-20_2350_test_free_avatar_upload.md deleted file mode 100644 index 39646d4c..00000000 --- a/docs/Pending_Features/вроде сделанное/2026-06-20_2350_test_free_avatar_upload.md +++ /dev/null @@ -1,25 +0,0 @@ -# Временная бесплатная загрузка аватара в Arweave - -- краткое описание фичи: - Добавлены два временных `Test...` API для бесплатной загрузки маленьких аватаров в Arweave через серверный кошелёк с лимитом `3` загрузки на пользователя. В UI мастера смены аватара добавлен пункт `Залить аватар бесплатно`. - -- что именно проверять: - 1. Пользователь с активной сессией открывает редактирование профиля. - 2. По нажатию на аватар открывается мастер `Сменить аватар`. - 3. В мастере есть пункт `Залить аватар бесплатно`. - 4. До первой загрузки UI показывает остаток `3 из 3`. - 5. Маленький JPEG/PNG/WebP после уменьшения до файла <= `128 KB` успешно уходит через `TestUploadFreeAvatar`. - 6. После загрузки приходит `txId`, и аватар сохраняется в профиль как `avatar.ar`. - 7. Остаток уменьшается: `2`, `1`, `0`. - 8. На четвёртой попытке сервер отвечает понятной ошибкой про исчерпанный бесплатный лимит. - 9. Если итоговый уменьшенный файл всё ещё > `128 KB`, UI не отправляет его и показывает понятную ошибку. - 10. Если серверный Arweave JWK/path не настроен, UI получает понятную ошибку временной функции. - -- ожидаемый результат: - - первые 3 маленькие аватарки загружаются через серверный Arweave-кошелёк; - - после каждой успешной загрузки `ava` в профиле указывает на новый `txId`; - - после исчерпания лимита дальнейшая бесплатная загрузка блокируется без записи в профиль; - - обычная загрузка через свой Arweave-кошелёк продолжает работать отдельно. - -- статус: - pending diff --git a/docs/Pending_Features/вроде сделанное/2026-06-24_1825_unified_channels_list_without_stories.md b/docs/Pending_Features/вроде сделанное/2026-06-24_1825_unified_channels_list_without_stories.md deleted file mode 100644 index 7e4eac91..00000000 --- a/docs/Pending_Features/вроде сделанное/2026-06-24_1825_unified_channels_list_without_stories.md +++ /dev/null @@ -1,28 +0,0 @@ -# Общий список каналов без stories - -- Краткое описание: - вкладка `Каналы` переведена на единый список без разделения на "мои" и "подписки". - Название канала в списке теперь показывается как `login_владельца/название_канала`. - Служебный канал `stories` скрыт из списка каналов, поиска, подписки и связанных UI-сценариев. - -- Что проверять: - 1. Открыть вкладку `Каналы`. - 2. Убедиться, что сразу показывается один общий список. - 3. Проверить, что свои и чужие каналы отображаются вместе. - 4. Проверить формат названий: `ownerLogin/channelName`. - 5. Открыть свой канал и убедиться, что внутри сохраняется UI владельца. - 6. Открыть чужой канал и убедиться, что внутри сохраняется UI подписчика. - 7. Проверить, что `stories` не отображается: - - в общем списке; - - в поиске каналов; - - в подписке на канал; - - в списках выбора канала для репоста. - -- Ожидаемый результат: - - вкладка `Каналы` больше не делится на два режима; - - все видимые каналы идут единым списком; - - `stories` нигде не виден и не предлагается пользователю; - - переход в канал сохраняет корректный UI в зависимости от владельца. - -- Статус: - `pending` diff --git a/docs/Pending_Features/вроде сделанное/2026-06-26_1500_addblock_tmp_bch_recovery.md b/docs/Pending_Features/вроде сделанное/2026-06-26_1500_addblock_tmp_bch_recovery.md deleted file mode 100644 index de2f63ef..00000000 --- a/docs/Pending_Features/вроде сделанное/2026-06-26_1500_addblock_tmp_bch_recovery.md +++ /dev/null @@ -1,47 +0,0 @@ -# Crash-safe запись обычного `AddBlock` через `tmp_bch` - -## Кратко - -Обычный `AddBlock` переведён на схему: - -1. сборка `.tmp_bch`; -2. запись sidecar `.write_check` с `blockNumber` и `blockHash`; -3. создание пустого marker `.write_pending`; -4. SQL-транзакция; -5. атомарная подмена `tmp -> main`; -6. удаление временных файлов. - -## Что проверить - -1. Обычный `AddBlock` на свежей цепочке. -2. Падение до SQL-commit: - - должны остаться только временные файлы; - - на старте они должны быть удалены. -3. Падение после SQL-commit, но до `atomicReplaceBlockchainFile(...)`: - - на старте recovery должен довести swap до конца. -4. Падение после `atomicReplaceBlockchainFile(...)`, но до удаления marker/sidecar: - - на старте recovery должен просто подчистить хвост. -5. Сценарий без marker: - - `tmp_bch` / `write_check` считаются мусором и удаляются. - -## Ожидаемый результат - -- БД и файловая версия цепочки остаются согласованными. -- Повторный старт сервера не ломает chain и не требует ручной правки файлов. -- `BlockchainTmpRecoveryOnStartup` корректно обрабатывает и живые остатки, и мусор. - -## Статус - -`pending` - -## Что уже сделано - -- В коде есть `tmp_bch`, `write_check` и `write_pending`. -- `BlockchainWriter` пишет обычный `AddBlock` через временные артефакты. -- `BlockchainTmpRecoveryOnStartup` умеет добивать или чистить незавершённую запись. - -## Что ещё перепроверить - -- ручной crash-test на тестовом сервере; -- совместимость с уже существующими `resync_pending` marker-файлами; -- отсутствие ложных срабатываний на старых временных файлах. diff --git a/docs/Pending_Features/вроде сделанное/2026-06-26_1745_proverka_avariynykh_ostanovok.md b/docs/Pending_Features/вроде сделанное/2026-06-26_1745_proverka_avariynykh_ostanovok.md deleted file mode 100644 index d6dbab0d..00000000 --- a/docs/Pending_Features/вроде сделанное/2026-06-26_1745_proverka_avariynykh_ostanovok.md +++ /dev/null @@ -1,29 +0,0 @@ -# Проверка аварийных остановок на разных этапах - -## Кратко - -Нужно отдельно проверить, как сервер восстанавливается после внезапной остановки: - -1. во время обычного `AddBlock` / `tmp_bch`-pipeline; -2. во время `full resync` цепочки; -3. во время startup recovery, если остановка произошла на предыдущем запуске; -4. при обычном апгрейде сервиса без явного crash-сценария. - -## Что проверять - -1. Остановка сервиса до `commit` БД. -2. Остановка сервиса после `commit`, но до замены `main.bch`. -3. Остановка сервиса во время `BlockchainResyncCleanupDAO`. -4. Остановка сервиса во время повторной загрузки цепочки по `GetBlockchainBlock`. -5. Поведение при обычном `systemctl restart`, когда сервер сам должен добить recovery. - -## Ожидаемый результат - -- после старта сервер либо дочищает временные артефакты, либо завершает незаконченный `resync`; -- не остаётся битых `.tmp_bch`, `.write_check`, `.write_pending`, `.resync_pending`; -- БД и файлы цепочки остаются согласованными; -- обычная работа сервера не стартует поверх незавершённого recovery. - -## Статус - -`pending` diff --git a/docs/Solana_Architecture/README.md b/docs/Solana_Architecture/README.md index d322f72b..55d37f97 100644 --- a/docs/Solana_Architecture/README.md +++ b/docs/Solana_Architecture/README.md @@ -105,7 +105,7 @@ DAO в текущем виде не является отдельной Anchor- ## Правило разделения с основным сервером -Solana-модуль лежит в основном репозитории как отдельная папка `shine-solana/shine/`, но не подключается автоматически к сборке или деплою основного сервера SHiNE. Команды `deployServer` и `deployUI` не должны деплоить Anchor-программы. Solana build/deploy выполняется отдельно из папки `shine-solana/shine/` по локальным правилам модуля. +Solana-модуль лежит в основном репозитории как отдельная папка `shine-solana/shine/`, но не подключается автоматически к сборке или деплою основного сервера SHiNE. Скрипты основного server/UI deploy из `deploy/scripts/` не должны деплоить Anchor-программы. Solana build/deploy выполняется отдельно из папки `shine-solana/shine/` по локальным правилам модуля. ## Движение денег diff --git a/docs/deploy/README.md b/docs/deploy/README.md deleted file mode 100644 index 0986ae42..00000000 --- a/docs/deploy/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# Деплой SHiNE (шаблон) - -Этот раздел хранит актуальные инструкции по деплою. - -## Базовый сервер - -- SSH: `player@shineup.me` -- Домен: `shineup.me` -- Базовый путь: `/home/player` - -Для всех рабочих инструкций и скриптов использовать доменное имя `shineup.me`, а не фиксированный IP: - -- актуальный IP должен браться через DNS-резолв на момент подключения; -- ручное дублирование IP в документации и deploy-скриптах не поддерживать. - -## Контуры деплоя - -- Production: - - SSH: `player@shineup.me` - - Домен: `shineup.me` - - IP: `178.208.64.62` -- Second production: - - SSH: `player@193.8.215.70` - - Домен: `server2.shineup.me` - - IP: `193.8.215.70` -## Локальные команды - -- Default server deploy: `./gradlew deployServer` или `./gradlew deployServerTest2` -- Default UI deploy: `./gradlew deployUI` или `./gradlew deployUITest2` -- Production server deploy: `./gradlew deployServerProduction` -- Production UI deploy: `./gradlew deployUIProduction` -- Локальный запуск: `./gradlew startLocal` - -## Отдельные тестовые VPS - -- Отдельный стенд с 4 devnet-серверами на одном VPS описан в: - - `docs/deploy/test-server/README.md` - -## Политика подтверждений - -- `shineup.me` и `server2.shineup.me` считать production-контурами. -- Любые изменения на production-контурах, включая deploy сервера, deploy UI, конфиги, перезапуски и миграции, делать только после отдельного явного подтверждения пользователя. -## Second production deploy (`server2.shineup.me`) - -- Это второй production-сервер SHiNE. -- Исторические задачи `deployServer`, `deployUI`, `deployServerTest2`, `deployUITest2` по-прежнему могут указывать сюда. -- Серверный deploy не запускает JUnit/IT-тесты на удалённом сервере. -- `deployServer` / `deployServerTest2` делают: - - сборку fat-jar локально; - - синхронизацию `data/` и `shine.sqlite` с production `shineup.me`; - - перенос `application.properties` с production с поправкой `server.ui.indexPath` на `/home/player/SHiNE/shine-ui/index.html`; - - установку `systemd` unit на `193.8.215.70`; - - перезапуск `shine-server.service`; - - установку/проверку Caddy для `server2.shineup.me`. -- `deployUI` / `deployUITest2` публикуют UI в `/home/player/SHiNE/shine-ui` на `193.8.215.70`. -- Важно: историческое имя `deployUITest2` вводит в заблуждение. По умолчанию эта задача деплоит на `server2.shineup.me`, а не на `t2.shineup.me`. - -## UI-деплой и Caddy (обязательно) - -- Целевая директория UI-деплоя: `/home/player/SHiNE/shine-ui`. -- `Caddyfile` на сервере должен смотреть в ту же директорию через `root * /home/player/SHiNE/shine-ui`. -- В `deploy_shine-PWA.sh` добавлена проверка: скрипт ищет блок `shineup.me { ... }` (или значение `EXPECTED_CADDY_SITE`) и проверяет `root` внутри этого блока. -- Если `root` внутри целевого блока не совпадает, деплой прерывается с ошибкой. -- Для ручного обхода проверки (только осознанно): `ALLOW_CADDY_MISMATCH=1 ./gradlew deployUI`. -- При необходимости можно явно переопределить путь деплоя: - - `REMOTE_UI_DIR=/нужный/путь ./gradlew deployUI` - - `EXPECTED_CADDY_UI_ROOT=/нужный/путь ./gradlew deployUI` - - `EXPECTED_CADDY_SITE=example.com ./gradlew deployUI` - -## Временные тестовые сайты Solana tickets - -- Для HTML UI программы `shine_payments` используется отдельный временный тестовый сайт. -- Основной каталог публикации: - - `/home/player/sites/test-solana-tickets.shineup.me` -- Рабочие домены: - - `https://test-solana-tickets.shineup.me` - - `https://test-solana-tickets.shiningpeople.ru` -- Назначение: - - ручная проверка сценариев покупки билетов; - - проверка DAO-инструментов и лимитов менеджеров; - - проверка ручного добавления билетов и `step_payout`. -- Эти сайты не считать основным UI SHiNE; это отдельная тестовая публикация под Solana-часть. - -### Важно для локального UI (history-router / Ctrl+F5) - -- Локальный UI **обязательно** поднимать только через `./gradlew startLocal`. -- Эта задача запускает `scripts/local_spa_server.py`, который делает SPA fallback: любой неизвестный путь (`/m/...`, `/channel/...`) возвращает `index.html`. -- Это обязательно для корректной работы `Ctrl+F5` на внутренних роутов без `404`. -- Рабочий URL выводится задачей в консоль в формате: `http://localhost:/?localWsPort=`. - -## Обязательные правила - -1. Перед серверным деплоем проверить локально. -2. При нестандартном деплое (другой хост, другая структура, ручные шаги) обязательно уточнить у пользователя, нужно ли обновить этот шаблон. -3. Если деплой-процесс изменился, этот файл и файлы в `servers/` обновлять в том же коммите. diff --git a/docs/deploy/servers/193.8.215.70_test2_main.md b/docs/deploy/servers/193.8.215.70_test2_main.md deleted file mode 100644 index 3bab829d..00000000 --- a/docs/deploy/servers/193.8.215.70_test2_main.md +++ /dev/null @@ -1,43 +0,0 @@ -# Сервер `193.8.215.70` — второй production (`server2.shineup.me`) - -- Пользователь: `player` -- Домен: `server2.shineup.me` -- Логин сервера: `server2shineupme` -- Каталог SHiNE: `/home/player/SHiNE` -- UI публикация для Caddy: `/home/player/SHiNE/shine-ui` -- Сервер: `/home/player/SHiNE/shine-server/shine-server.jar` -- Данные: `/home/player/SHiNE/shine-server/data/` - - `shine.sqlite` - - `*.bch` -- Логи сервера: `/home/player/SHiNE/shine-server/logs/app.log` - -## Сервисы - -- `shine-server.service` (systemd) -- `caddy.service` (systemd) - -## Статус - -- Это второй production-сервер SHiNE. -- Исторические имена deploy-задач могут по-прежнему ссылаться на него как на `test2`. -- В документации и в списке окружений считать его production-контуром. - -## Caddy - -- Конфиг: `/etc/caddy/Caddyfile` -- Сайты: - - `server2.shineup.me` - - `agent.shiningpeople.ru` -- Для `server2.shineup.me`: - - `root * /home/player/SHiNE/shine-ui` - - `try_files {path} /index.html` - - `reverse_proxy /ws* -> 127.0.0.1:7070` - -## Deploy - -- Default server deploy: - - `./gradlew deployServer` - - `./gradlew deployServerTest2` -- Default UI deploy: - - `./gradlew deployUI` - - `./gradlew deployUITest2` diff --git a/docs/deploy/servers/shineup.me_main.md b/docs/deploy/servers/shineup.me_main.md deleted file mode 100644 index 3e947382..00000000 --- a/docs/deploy/servers/shineup.me_main.md +++ /dev/null @@ -1,48 +0,0 @@ -# Сервер `shineup.me` — основной - -- SSH: `player@shineup.me` -- Определение IP: через DNS-резолв домена `shineup.me` на момент подключения -- Текущий IP на момент последнего обновления документа: `178.208.64.62` -- Пользователь: `player` -- Базовый путь: `/home/player` -- Каталог SHiNE: `/home/player/SHiNE` -- UI публикация: `/home/player/SHiNE/shine-ui` -- Сервер: `/home/player/SHiNE/shine-server/shine-server.jar` -- Данные: `/home/player/SHiNE/shine-server/data/` -- Логи сервера: `/home/player/SHiNE/shine-server/logs/app.log` - -## Сервисы - -- `shine-server.service` (systemd) -- `caddy.service` (systemd) - -## Caddy - -- Активный конфиг (через systemd `ExecStart`): `/etc/caddy/Caddyfile` -- Для UI: - - `root * /home/player/SHiNE/shine-ui` - - `try_files {path} /index.html` (SPA fallback) - - no-cache заголовки - - `reverse_proxy /ws* -> 127.0.0.1:7070` - -## Дополнительно - -- Для отдельной админки `shine_payments` используется каталог: - - `/home/player/sites/test-solana-tickets.shineup.me` -- Эта публикация используется как временный тестовый сайт для сценариев покупки билетов и выплат `shine_payments`. -- Домены этой публикации: - - `https://test-solana-tickets.shineup.me` - - `https://test-solana-tickets.shiningpeople.ru` -- Для всех deploy-скриптов и инструкций использовать именно `player@shineup.me`, без жёсткой фиксации IP. - -## Правило изменений - -- `shineup.me` — production. -- Любые изменения на этом сервере делать только после отдельного явного подтверждения пользователя. - -## Deploy - -- Production deploy-задачи: - - `./gradlew deployServerProduction` - - `./gradlew deployUIProduction` -- Default deploy-задачи `./gradlew deployServer` и `./gradlew deployUI` сюда больше не относятся. diff --git a/docs/deploy/test-server/178.208.90.249_quad_devnet.md b/docs/deploy/test-server/178.208.90.249_quad_devnet.md deleted file mode 100644 index adda81e1..00000000 --- a/docs/deploy/test-server/178.208.90.249_quad_devnet.md +++ /dev/null @@ -1,173 +0,0 @@ -# VPS `178.208.90.249` (`player`) — 4 тестовых SHiNE-сервера на devnet - -## Назначение - -Этот VPS используется как отдельный тестовый стенд для одновременного запуска 4 SHiNE-серверов: -- `server_t1` → `https://t1.shineup.me` -- `server_t2` → `https://t2.shineup.me` -- `server_t3` → `https://t3.shineup.me` -- `server_t4` → `https://t4.shineup.me` - -Все 4 инстанса работают через Solana `devnet`. - -## Каталоги - -Структура в домашней папке пользователя `player`: -- `/home/player/t1/server` -- `/home/player/t1/UI` -- `/home/player/t2/server` -- `/home/player/t2/UI` -- `/home/player/t3/server` -- `/home/player/t3/UI` -- `/home/player/t4/server` -- `/home/player/t4/UI` - -Дополнительно: -- подробная памятка на самом сервере: `/home/player/Agents.md` - -## Порты и systemd - -Соответствие инстансов: -- `t1` → localhost `7101` → `shine-t1.service` -- `t2` → localhost `7102` → `shine-t2.service` -- `t3` → localhost `7103` → `shine-t3.service` -- `t4` → localhost `7104` → `shine-t4.service` - -Каждый unit запускает один и тот же jar: -- `/home/player/tX/server/shine-server.jar` - -Рабочая директория каждого unit: -- `/home/player/tX/server` - -Это важно, потому что сервер читает внешний `application.properties` именно из текущей рабочей директории. - -## Конфиги сервера - -У каждого инстанса свой файл: -- `/home/player/tX/server/application.properties` - -Ключевые параметры в нём: -- `server.port=710X` -- `server.SHiNE.login=server_tX` -- `db.path=data/shine.sqlite` -- `solana.cluster=devnet` -- `solana.rpcUrl=https://api.devnet.solana.com` -- `server.ui.indexPath=/home/player/tX/UI/index.html` -- `server.info.url=https://tX.shineup.me` -- `server.info.origin=devnet` - -Важно: -- Program ID SHiNE одинаковые для mainnet и devnet. -- Поэтому для перевода инстанса на devnet достаточно правильных `solana.cluster` и `solana.rpcUrl`. - -## Конфиги UI - -У каждого домена лежит отдельная копия `shine-UI`. - -В каждой копии меняется `js/deploy-config.js`: -- `defaultServerLogin=server_tX` -- `defaultServerAddress=tX.shineup.me` -- `defaultSolanaCluster=devnet` -- `defaultSolanaEndpoint=https://api.devnet.solana.com` - -За счёт этого: -- UI по умолчанию открывает именно свой сервер -- `server-ui` формы по умолчанию используют именно `devnet` - -## Caddy - -Конфиг: -- `/etc/caddy/Caddyfile` - -Логика по каждому сайту одинаковая: -- статические файлы берутся из `/home/player/tX/UI` -- путь `/ws` проксируется на `127.0.0.1:710X` - -Права доступа: -- каталог `/home/player` и `/home/player/tX` должен быть доступен на `+x` для чтения через Caddy -- все каталоги и файлы в `/home/player/tX/UI` должны быть читаемы пользователем `caddy` - -## Что уже проверено - -После настройки было подтверждено: -- `https://t1.shineup.me` отвечает `HTTP 200` -- `https://t2.shineup.me` отвечает `HTTP 200` -- `https://t3.shineup.me` отвечает `HTTP 200` -- `https://t4.shineup.me` отвечает `HTTP 200` -- `Caddy` успешно выпустил сертификаты Let's Encrypt на все 4 домена -- все 4 процесса Java слушают свои порты `7101..7104` -- в логах есть строка `WS сервер запущен на ws://localhost:710X/ws` - -## Важный operational-нюанс - -Официальный `https://api.devnet.solana.com` может отдавать `HTTP 429`, если несколько инстансов одновременно делают bootstrap PDA/sync-серверов на старте. - -На практике это уже проявилось: -- `t3` и `t4` подтянули `sync_servers` сразу -- `t1` и `t2` на первом одновременном старте словили `429` -- после последовательного рестарта `shine-t1` и `shine-t2` они тоже успешно сохранили `sync_servers` - -Если после очередного деплоя какой-то инстанс не подтянул `sync_servers`, сначала делать не массовый рестарт, а по одному: - -```bash -sudo systemctl restart shine-t1 -sleep 8 -sudo systemctl restart shine-t2 -sleep 8 -sudo systemctl restart shine-t3 -sleep 8 -sudo systemctl restart shine-t4 -``` - -## Как обновлять сервер - -1. Локально собрать jar: - -```bash -./gradlew shadowJar -``` - -2. Залить `SHiNE-server/build/libs/shine-server.jar` в каждый нужный каталог: -- `/home/player/t1/server/shine-server.jar` -- `/home/player/t2/server/shine-server.jar` -- `/home/player/t3/server/shine-server.jar` -- `/home/player/t4/server/shine-server.jar` - -3. Если менялся runtime-конфиг, обновить соответствующий `application.properties`. - -4. Перезапускать сервисы лучше по одному, с паузой, чтобы снизить шанс `429` от devnet RPC. - -## Как обновлять UI - -1. Взять свежую локальную папку `shine-UI/`. -2. Для каждой копии подставить свой `deploy-config.js`. -3. Скопировать файлы в `/home/player/tX/UI/`. -4. Проверить права чтения для Caddy. - -## Полезные команды на VPS - -Проверка сервисов: - -```bash -sudo systemctl --no-pager --full status caddy shine-t1 shine-t2 shine-t3 shine-t4 -``` - -Перезапуск одного инстанса: - -```bash -sudo systemctl restart shine-t1 -``` - -Логи одного инстанса: - -```bash -tail -n 200 /home/player/t1/server/logs/app.log -sudo journalctl -u shine-t1 -n 200 --no-pager -``` - -Проверка Caddy: - -```bash -sudo caddy validate --config /etc/caddy/Caddyfile -curl -I https://t1.shineup.me -``` diff --git a/docs/deploy/test-server/README.md b/docs/deploy/test-server/README.md deleted file mode 100644 index 33f51f3b..00000000 --- a/docs/deploy/test-server/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Тестовый VPS с 4 SHiNE-серверами - -В этой папке описан отдельный тестовый VPS `178.208.90.249`, на котором подняты 4 независимых SHiNE-инстанса под доменами `t1.shineup.me` ... `t4.shineup.me`. - -Текущая основная схема: -- пользователь на VPS: `player` -- все 4 инстанса работают через `devnet` -- каждый инстанс имеет свой каталог `server`, свой каталог `UI`, свой `systemd` unit и свой localhost-порт -- внешний HTTPS и маршрутизацию `/ws` обслуживает один общий `Caddy` - -Детальное описание: -- [178.208.90.249_quad_devnet.md](/home/ai/work/SHiNE/SHiNE-server-sha256/docs/deploy/test-server/178.208.90.249_quad_devnet.md) diff --git a/docs/instructions/coturn-install.md b/docs/instructions/coturn-install.md deleted file mode 100644 index a714882a..00000000 --- a/docs/instructions/coturn-install.md +++ /dev/null @@ -1,75 +0,0 @@ -# Установка TURN сервера (coturn) - -## 1. Что нужно -- Сервер с публичным IP (в примере: `37.214.58.208`). -- Доступ `root` по SSH. -- Открытые порты в firewall: - - `3478/tcp` - - `3478/udp` - - диапазон relay-портов, например `49160-49200/udp` - -## 2. Быстрая установка (рекомендуется) -В проекте уже есть готовый скрипт: - -```bash -sudo bash scripts/setup_turn_coturn.sh \ - --secret "CHANGE_ME_LONG_RANDOM_SECRET" \ - --realm "shineup.me" -``` - -Что делает скрипт: -- ставит `coturn`; -- включает режим `use-auth-secret` (временные логин/пароль); -- пишет `/etc/turnserver.conf`; -- включает и перезапускает сервис `coturn`. - -## 3. Проверка -Проверить статус: - -```bash -sudo systemctl status coturn --no-pager -``` - -Проверить, что порт слушается: - -```bash -sudo ss -lntup | grep 3478 -``` - -## 4. Ручная установка (если без скрипта) -```bash -sudo apt-get update -sudo apt-get install -y coturn -``` - -Пример `/etc/turnserver.conf`: - -```conf -listening-port=3478 -fingerprint -lt-cred-mech -use-auth-secret -static-auth-secret=CHANGE_ME_LONG_RANDOM_SECRET -realm=shineup.me -external-ip=37.214.58.208 -listening-ip=0.0.0.0 -relay-ip=37.214.58.208 -min-port=49160 -max-port=49200 -no-cli -simple-log -``` - -В `/etc/default/coturn`: - -```conf -TURNSERVER_ENABLED=1 -``` - -Запуск: - -```bash -sudo systemctl enable coturn -sudo systemctl restart coturn -``` - diff --git a/docs/instructions/turn-connect-to-shine-server.md b/docs/instructions/turn-connect-to-shine-server.md deleted file mode 100644 index ababbc6b..00000000 --- a/docs/instructions/turn-connect-to-shine-server.md +++ /dev/null @@ -1,48 +0,0 @@ -# Подключение TURN к SHiNE-серверу - -Начиная с текущей версии, клиент звонков запрашивает ICE-конфиг у backend через WS-операцию `GetCallIceConfig` и использует её для `RTCPeerConnection`. - -## 1. Настройки backend -Файл: `src/main/resources/application.properties` - -Ключи: - -```properties -call.ice.stun.urls=stun:stun.l.google.com:19302 -call.ice.turn.urls=turn:37.214.58.208:3478?transport=udp,turn:37.214.58.208:3478?transport=tcp -call.ice.turn.ttlSec=600 -call.ice.turn.userPrefix=shine -call.ice.turn.sharedSecret=CHANGE_ME_LONG_RANDOM_SECRET - -# fallback (если не используете shared-secret) -call.ice.turn.username= -call.ice.turn.password= -``` - -## 2. Рекомендуемый режим (временные credentials) -- На coturn и на SHiNE-сервере должен быть **одинаковый** secret: - - coturn: `static-auth-secret=...` - - SHiNE: `call.ice.turn.sharedSecret=...` -- Тогда SHiNE выдаёт короткоживущие `turnUsername/turnPassword` (TTL). - -## 3. Fallback режим (статический логин/пароль) -Если временные credentials не используются: - -```properties -call.ice.turn.sharedSecret= -call.ice.turn.username=turn_user -call.ice.turn.password=turn_password -``` - -## 4. Деплой после изменения -```bash -./gradlew deployServerNoCleanNoTests -./gradlew deployWEB -``` - -## 5. Проверка -1. Авторизоваться двумя клиентами. -2. Запустить звонок. -3. Проверить, что звонок устанавливается даже в сети, где прямой P2P затруднён. -4. Если TURN недоступен, клиент автоматически откатится к STUN-конфигу по умолчанию. - diff --git a/scripts/install_test2_caddyfile.sh b/scripts/install_test2_caddyfile.sh deleted file mode 100644 index 4bcb6c4c..00000000 --- a/scripts/install_test2_caddyfile.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -TARGET_HOST="${TARGET_HOST:-player@193.8.215.70}" -TARGET_DOMAIN="${TARGET_DOMAIN:-server2.shineup.me}" -REMOTE_UI_DIR="${REMOTE_UI_DIR:-/home/player/SHiNE/shine-ui}" -REMOTE_CADDYFILE="${REMOTE_CADDYFILE:-/etc/caddy/Caddyfile}" - -TMP_DIR="$(mktemp -d)" -cleanup() { - rm -rf "$TMP_DIR" -} -trap cleanup EXIT - -cat >"$TMP_DIR/Caddyfile" </dev/null -ssh "$TARGET_HOST" "sudo -n true" -rsync -az "$TMP_DIR/Caddyfile" "$TARGET_HOST:/tmp/caddy-test2.new" -ssh "$TARGET_HOST" "set -euo pipefail; \ - sudo mv -f /tmp/caddy-test2.new '$REMOTE_CADDYFILE'; \ - sudo chown root:root '$REMOTE_CADDYFILE'; \ - sudo caddy validate --config '$REMOTE_CADDYFILE'; \ - sudo systemctl restart caddy" diff --git a/server-backup/README.md b/server-backup/README.md deleted file mode 100644 index d40e59fe..00000000 --- a/server-backup/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# server-backup - -- `archive/` — локальные полные бэкапы по датам (не коммитятся). -- `scheme/` — лёгкая схема восстановления (коммитится). -- `backup-version.properties` — версии схемы и полного бэкапа. - -Текущий сервер-источник: `shineup.me`. diff --git a/shine-UI/js/pages/registration-payment-view.js b/shine-UI/js/pages/registration-payment-view.js index 02ccdb0b..8240524f 100644 --- a/shine-UI/js/pages/registration-payment-view.js +++ b/shine-UI/js/pages/registration-payment-view.js @@ -16,6 +16,7 @@ import { } from '../services/solana-wallet-service.js'; import { loadSolanaWeb3 } from '../vendor/solana-web3-loader.js'; import { + checkLoginExistsOnSolana, formatSolanaErrorDetails, isUserAlreadyExistsSolanaError, registerUserOnSolana, @@ -24,8 +25,13 @@ import { defaultServerLogin } from '../deploy-config.js'; export const pageMeta = { id: 'registration-payment-view', title: 'Оплата регистрации', showAppChrome: false }; const MIN_REQUIRED_SOL = 0.01; -const AUTO_LOGIN_INITIAL_DELAY_MS = 10000; +const AUTO_LOGIN_INITIAL_DELAY_MS = 1000; const AUTO_LOGIN_RETRY_MS = 2000; +const REGISTRATION_PROGRESS_DURATION_MS = 12000; +const REGISTRATION_POLL_START_DELAY_MS = 4000; +const REGISTRATION_POLL_INTERVAL_MS = 2000; +const REGISTRATION_CONFIRM_TIMEOUT_MS = 25000; +const REGISTRATION_SUCCESS_SETTLE_DELAY_MS = 2000; const EMPTY_PASSWORD_WORDS = Array.from({ length: 12 }, () => ''); function getExplorerClusterName(endpoint) { @@ -60,6 +66,10 @@ function getCryptoRuntimeState() { return { hasCrypto, hasGetRandomValues, hasSubtle, secureContext }; } +function clamp(value, min, max) { + return Math.max(min, Math.min(max, value)); +} + async function completeRegistrationLogin({ navigate, keyBundle }) { await authService.reconnect(state.entrySettings.shineServer); const result = await authService.createSessionForExistingUser( @@ -299,7 +309,7 @@ export function render({ navigate }) { } } - renderSolanaDoneStage({ navigate, status, keyBundle, registrationTxId }); + renderSolanaRegistrationStage({ navigate, status, keyBundle, registrationTxId }); } catch (error) { const message = toUserMessage(error, 'Не удалось завершить регистрацию.'); setAuthError(message); @@ -345,6 +355,192 @@ export function render({ navigate }) { return screen; } +function renderSolanaRegistrationStage({ navigate, status, keyBundle, registrationTxId = '' }) { + const screen = document.querySelector('section.stack'); + if (!screen) return; + const headerBackButton = screen.querySelector('.page-header .header-left .icon-btn'); + const card = screen.querySelector('.card.stack'); + if (!card) return; + card.classList.add('registration-finish-card'); + + let progressTimerId = null; + let pollStartTimerId = null; + let pollTimerId = null; + let successTimerId = null; + let confirmationInFlight = false; + let stageClosed = false; + let successPending = false; + let timeoutShown = false; + const stageStartedAt = Date.now(); + const txExplorerUrl = makeSolanaExplorerTxUrl(registrationTxId, state.entrySettings.solanaServer); + + const title = document.createElement('h2'); + title.className = 'registration-finish-title'; + title.textContent = 'Идёт регистрация в блокчейне...'; + + const hint = document.createElement('p'); + hint.className = 'auth-copy registration-finish-text'; + hint.textContent = 'Ждём, пока транзакция будет полностью одобрена сетью Solana.'; + + const txIdLine = document.createElement('p'); + txIdLine.className = 'meta-muted registration-finish-tx'; + if (registrationTxId && txExplorerUrl) { + const txLabel = document.createElement('span'); + txLabel.textContent = 'Tx ID регистрации: '; + const txLink = document.createElement('a'); + txLink.className = 'registration-finish-tx-link'; + txLink.href = txExplorerUrl; + txLink.target = '_blank'; + txLink.rel = 'noopener noreferrer'; + txLink.textContent = registrationTxId; + txIdLine.append(txLabel, txLink); + } else { + txIdLine.textContent = 'Tx ID регистрации: ожидаем подтверждённую подпись'; + } + + const progressWrap = document.createElement('div'); + progressWrap.className = 'registration-progress'; + + const progressBar = document.createElement('div'); + progressBar.className = 'registration-progress-bar'; + progressWrap.append(progressBar); + + const progress = document.createElement('p'); + progress.className = 'meta-muted registration-finish-progress'; + progress.textContent = 'Подготавливаем проверку подтверждения...'; + + const pollStatus = document.createElement('p'); + pollStatus.className = 'meta-muted registration-finish-progress'; + pollStatus.textContent = 'Через несколько секунд начнём проверять подтверждение регистрации.'; + + const stopTimers = () => { + if (progressTimerId) { + window.clearInterval(progressTimerId); + progressTimerId = null; + } + if (pollStartTimerId) { + window.clearTimeout(pollStartTimerId); + pollStartTimerId = null; + } + if (pollTimerId) { + window.clearInterval(pollTimerId); + pollTimerId = null; + } + if (successTimerId) { + window.clearTimeout(successTimerId); + successTimerId = null; + } + }; + + const updateVisualProgress = () => { + const elapsed = Date.now() - stageStartedAt; + let widthPercent = 0; + if (elapsed <= REGISTRATION_PROGRESS_DURATION_MS) { + const phaseRatio = clamp(elapsed / REGISTRATION_PROGRESS_DURATION_MS, 0, 1); + widthPercent = 100 * (1 - ((1 - phaseRatio) ** 1.85)); + } else { + const extraRatio = 1 - Math.exp(-(elapsed - REGISTRATION_PROGRESS_DURATION_MS) / 9000); + widthPercent = 88 + (10 * clamp(extraRatio, 0, 1)); + } + progressBar.style.width = `${clamp(widthPercent, 0, 98)}%`; + + if (elapsed < REGISTRATION_POLL_START_DELAY_MS) { + progress.textContent = 'Отправили регистрацию в сеть. Даём транзакции несколько секунд на обработку.'; + return; + } + if (elapsed < REGISTRATION_CONFIRM_TIMEOUT_MS) { + progress.textContent = 'Идёт ожидание подтверждения Solana. Индикатор может замедлиться, это нормально.'; + return; + } + progress.textContent = 'Подтверждение затянулось. Продолжаем автоматическую проверку.'; + }; + + const finalizeSuccess = () => { + if (stageClosed || successPending) return; + successPending = true; + stopTimers(); + progress.textContent = 'Подтверждение получено. Завершаем регистрацию...'; + pollStatus.textContent = 'Запись уже найдена в Solana, готовим финальный экран.'; + status.style.display = 'none'; + progressBar.style.transition = `width ${REGISTRATION_SUCCESS_SETTLE_DELAY_MS}ms ease-out`; + progressBar.style.width = '100%'; + successTimerId = window.setTimeout(() => { + if (stageClosed) return; + stageClosed = true; + renderSolanaDoneStage({ navigate, status, keyBundle, registrationTxId }); + }, REGISTRATION_SUCCESS_SETTLE_DELAY_MS); + }; + + const showTimeoutState = () => { + if (timeoutShown || stageClosed) return; + timeoutShown = true; + status.className = 'status-line is-unavailable'; + status.textContent = 'Подтверждение не пришло вовремя. Возможно, регистрация уже прошла, а возможно ещё нет. Проверьте Tx ID ниже: мы продолжим автоматическую проверку.'; + status.style.display = ''; + pollStatus.textContent = 'Пока подтверждения нет. Подождите ещё немного, мы продолжаем проверять регистрацию.'; + }; + + const tryCheckRegistration = async () => { + if (stageClosed || confirmationInFlight) return; + confirmationInFlight = true; + progress.textContent = 'Проверяем подтверждение регистрации в Solana...'; + status.style.display = timeoutShown ? '' : 'none'; + try { + const result = await checkLoginExistsOnSolana({ + login: state.registrationDraft.login, + solanaEndpoint: state.entrySettings.solanaServer, + }); + if (result?.exists) { + finalizeSuccess(); + return; + } + pollStatus.textContent = 'Пока ещё не прошла, подождите ещё немного...'; + if ((Date.now() - stageStartedAt) >= REGISTRATION_CONFIRM_TIMEOUT_MS) { + showTimeoutState(); + } + } catch (error) { + console.warn('Registration confirmation check failed', toUserMessage(error, 'registration-confirmation')); + pollStatus.textContent = 'Проверяем регистрацию повторно...'; + if ((Date.now() - stageStartedAt) >= REGISTRATION_CONFIRM_TIMEOUT_MS) { + showTimeoutState(); + } + } finally { + confirmationInFlight = false; + } + }; + + if (headerBackButton) { + const replacement = headerBackButton.cloneNode(true); + replacement.addEventListener('click', () => { + stageClosed = true; + stopTimers(); + navigate('start-view'); + }); + headerBackButton.replaceWith(replacement); + } + + card.innerHTML = ''; + status.style.display = 'none'; + card.append(title, hint, txIdLine, progressWrap, progress, pollStatus, status); + + updateVisualProgress(); + progressTimerId = window.setInterval(() => { + if (stageClosed) return; + updateVisualProgress(); + if ((Date.now() - stageStartedAt) >= REGISTRATION_CONFIRM_TIMEOUT_MS) { + showTimeoutState(); + } + }, 160); + + pollStartTimerId = window.setTimeout(() => { + if (stageClosed) return; + void tryCheckRegistration(); + pollTimerId = window.setInterval(() => { + void tryCheckRegistration(); + }, REGISTRATION_POLL_INTERVAL_MS); + }, REGISTRATION_POLL_START_DELAY_MS); +} + function renderSolanaDoneStage({ navigate, status, keyBundle, registrationTxId = '' }) { const screen = document.querySelector('section.stack'); if (!screen) return; @@ -365,7 +561,7 @@ function renderSolanaDoneStage({ navigate, status, keyBundle, registrationTxId = const hint = document.createElement('p'); hint.className = 'auth-copy registration-finish-text'; - hint.textContent = 'Подождите 10 секунд, пока обновится транзакция вашей регистрации в блокчейне Solana. После этого вход в аккаунт произойдёт автоматически.'; + hint.textContent = 'Регистрация подтверждена в блокчейне Solana. Сейчас выполним автоматический вход в аккаунт.'; const txIdLine = document.createElement('p'); txIdLine.className = 'meta-muted registration-finish-tx'; diff --git a/tools/understand-anything-lab/README.md b/tools/understand-anything-lab/README.md index 19078330..82067cdf 100644 --- a/tools/understand-anything-lab/README.md +++ b/tools/understand-anything-lab/README.md @@ -48,7 +48,7 @@ ## Что не делать без отдельного решения - Не включать `Understand Anything` в Gradle-сборку. -- Не добавлять его в `deployServer` или `deployUI`. +- Не добавлять его в основной server/UI deploy из `deploy/scripts/`. - Не переносить серверные модули в новую папку одновременно с этим экспериментом. - Не включать auto-update hook через `/understand --auto-update`, пока не понятно, нужен ли граф в каждом commit. @@ -62,4 +62,3 @@ ``` До такого решения артефакты графа лучше считать локальными. -