diff --git a/docs/DEPLOY_SOVEREIGN_SCARAB_V4.md b/docs/DEPLOY_SOVEREIGN_SCARAB_V4.md new file mode 100644 index 00000000..aea81d03 --- /dev/null +++ b/docs/DEPLOY_SOVEREIGN_SCARAB_V4.md @@ -0,0 +1,237 @@ +# DEPLOY — Sovereign Scarab v4 (L-SS2) + +> **Anchor:** φ² + φ⁻² = 3 +> **Статус:** Операционная инструкция +> **Epic:** [gHashTag/trios#940](https://github.com/gHashTag/trios/issues/940) +> **Issue:** [gHashTag/trios-railway#210](https://github.com/gHashTag/trios-railway/issues/210) +> **Образ:** `ghcr.io/ghashtag/sovereign-scarab:v4` +> **Публикация образа:** `.github/workflows/sovereign-scarab.yml` (L-SS1, PR #159 — не трогать) +> **Post-deploy управление:** queen-hive-mcp (L-SS3, PR #161) + +--- + +## 1. Цель и предусловия + +### 1.1 Цель + +Задеплоить **27 идентичных сервисов** `sovereign-scarab:v4` на Railway. +Каждый сервис — автономный heartbeat-агент, который: + +- подключается к Trinity SSOT через `DATABASE_URL`, +- записывает пульс в `ssot.scarab_heartbeat` каждые `HEARTBEAT_INTERVAL_S` секунд, +- опрашивает очередь задач с интервалом `POLL_INTERVAL_MS` мс, +- пишет structured-логи (`RUST_LOG=info,sovereign_scarab=debug`). + +### 1.2 Предусловия + +| № | Предусловие | Ответственный | +|---|------------|---------------| +| P-01 | Образ `ghcr.io/ghashtag/sovereign-scarab:v4` опубликован (workflow L-SS1 прошёл) | CI/CD | +| P-02 | Railway-аккаунты ACC1 / ACC2 / ACC3 созданы и верифицированы | Оператор | +| P-03 | Каждый аккаунт имеет активный Project с достаточным лимитом сервисов (≥ 9) | Оператор | +| P-04 | `DATABASE_URL` для каждого сервиса указывает на **Trinity SSOT** (единый источник истины) | Оператор | +| P-05 | Таблица `ssot.scarab_heartbeat` существует и доступна для INSERT | DBA | +| P-06 | Таблица `ssot.scarab_audit_log` существует (для G-SS-05) | DBA | +| P-07 | GHCR-пакет публичный **или** Railway имеет pull-секрет для `ghcr.io/ghashtag` | DevOps | + +> ⚠️ **ВАЖНО:** `DATABASE_URL` каждого из 27 сервисов **должен** указывать на Trinity SSOT. +> Использование отдельных БД нарушит консистентность heartbeat-счётчика. + +> ℹ️ **Mass-deploy workflows устарели:** PR #214 (замерджен) задепрекейтил автоматические +> mass-deploy workflow. Деплой 27 сервисов выполняется **вручную** по настоящей инструкции +> или через queen-hive-mcp (L-SS3, PR #161). + +--- + +## 2. Переменные окружения (per service) + +Каждый из 27 сервисов должен получить следующий набор env-переменных: + +| Переменная | Значение | Описание | +|-----------|---------|---------| +| `DATABASE_URL` | `postgresql://:@:/` | Строка подключения к Trinity SSOT — **уникальна для каждого аккаунта** | +| `RAILWAY_SERVICE_ID` | `` | Автоматически задаётся Railway; при ручном деплое — UUID сервиса | +| `TRAIN_DATA` | `fineweb` | Идентификатор датасета | +| `POLL_INTERVAL_MS` | `2000` | Интервал опроса очереди, миллисекунды | +| `HEARTBEAT_INTERVAL_S` | `30` | Интервал heartbeat в БД, секунды | +| `RUST_LOG` | `info,sovereign_scarab=debug` | Уровень логирования | + +> `RAILWAY_SERVICE_ID` Railway проставляет автоматически в runtime. Явно задавать его +> нужно только при локальном тестировании или нестандартных деплоях. + +--- + +## 3. Шаги деплоя через Railway UI (один сервис) + +> Повторить для каждого из 27 сервисов. + +``` +Railway Dashboard + └─ [Выбрать Project] + └─ "+ New Service" + └─ "Docker Image" + └─ Ввести: ghcr.io/ghashtag/sovereign-scarab:v4 + └─ "Deploy" + └─ [Открыть сервис] → "Variables" + └─ "+ Add Variable" (повторить для каждой переменной): + DATABASE_URL = + TRAIN_DATA = fineweb + POLL_INTERVAL_MS = 2000 + HEARTBEAT_INTERVAL_S = 30 + RUST_LOG = info,sovereign_scarab=debug + └─ "Redeploy" (применить переменные) + └─ [Logs] → убедиться, что нет FATAL / panics +``` + +### 3.1 Именование сервисов + +Рекомендуемый шаблон: `scarab-{account}-{n:02}`, например: + +- `scarab-acc1-01` … `scarab-acc1-09` +- `scarab-acc2-01` … `scarab-acc2-09` +- `scarab-acc3-01` … `scarab-acc3-09` + +### 3.2 Healthcheck + +Healthcheck Railway (`HEALTHCHECK`) **не используется** — мониторинг состояния ведётся +через запись heartbeat-строк в `ssot.scarab_heartbeat`. Smoke-test описан в разделе 5. + +--- + +## 4. Шаги деплоя через Railway CLI + +> Railway CLI (`railway`) должен быть установлен: `npm i -g @railway/cli` или через homebrew. + +```bash +# 1. Авторизация +railway login + +# 2. Привязка к проекту (выполнить один раз per проект) +railway link + +# 3. Создать новый сервис из Docker-образа +railway add --service scarab-acc1-01 + +# 4. Задать переменные окружения +railway variables set \ + DATABASE_URL="postgresql://..." \ + TRAIN_DATA="fineweb" \ + POLL_INTERVAL_MS="2000" \ + HEARTBEAT_INTERVAL_S="30" \ + RUST_LOG="info,sovereign_scarab=debug" \ + --service scarab-acc1-01 + +# 5. Задеплоить конкретный образ +railway up --image ghcr.io/ghashtag/sovereign-scarab:v4 --service scarab-acc1-01 + +# 6. Проверить логи +railway logs --service scarab-acc1-01 +``` + +> Повторить шаги 3–6 для каждого из 27 сервисов. +> Для массового деплоя можно обернуть в `for`-цикл, но убедитесь, что Railway API не +> rate-limit'ит запросы (рекомендуется пауза `sleep 2` между итерациями). + +--- + +## 5. Распределение 27 сервисов + +### Вариант A — Три аккаунта (рекомендуется) + +| Аккаунт | Проект | Сервисы | Количество | +|---------|--------|---------|-----------| +| ACC1 | trios-scarab-1 | scarab-acc1-01 … scarab-acc1-09 | 9 | +| ACC2 | trios-scarab-2 | scarab-acc2-01 … scarab-acc2-09 | 9 | +| ACC3 | trios-scarab-3 | scarab-acc3-01 … scarab-acc3-09 | 9 | + +**Преимущества:** изоляция по аккаунтам снижает риск исчерпания квоты Railway; упрощает +ротацию `DATABASE_URL` при смене пароля SSOT. + +### Вариант B — Один аккаунт + +Все 27 сервисов в одном проекте одного аккаунта. +**Применимо:** если Railway-план позволяет ≥ 27 активных сервисов. + +--- + +## 6. Smoke-test после деплоя + +После деплоя всех 27 сервисов выполнить запрос к Trinity SSOT: + +```sql +-- Ожидаемый результат: 27 +SELECT COUNT(DISTINCT canon_name) +FROM ssot.scarab_heartbeat +WHERE ts > now() - INTERVAL '60s'; +``` + +> Если счётчик < 27 — проверить логи отсутствующих сервисов через Railway UI/CLI. +> Типичные причины: неверный `DATABASE_URL`, образ не скачался (см. P-07). + +Дополнительная проверка audit-лога (G-SS-05): + +```sql +-- Ожидаем: нет строк с exit_code != 1 за последние 5 минут +SELECT canon_name, exit_code, created_at +FROM ssot.scarab_audit_log +WHERE created_at > now() - INTERVAL '5 minutes' + AND exit_code != 1 +ORDER BY created_at DESC; +``` + +--- + +## 7. Acceptance Criteria + +| ID | Критерий | Проверка | +|----|---------|---------| +| **G-SS-04** | Heartbeat coverage: все 27 сервисов пишут heartbeat не реже 1 раза в 60 секунд | `COUNT(DISTINCT canon_name) = 27` в `ssot.scarab_heartbeat` за последние 60 с | +| **G-SS-05** | Audit watchdog: ни один сервис не завершил watchdog-цикл с `exit_code != 1` | `SELECT COUNT(*) = 0` в `ssot.scarab_audit_log WHERE exit_code != 1` за последние 5 минут | + +Деплой считается **успешным** при выполнении обоих критериев одновременно. + +--- + +## 8. Rollback + +Для паузы отдельного сервиса без удаления используйте queen-hive-mcp (L-SS3, PR #161): + +```sql +-- Через Queen-Hive MCP +SELECT ssot.pause_scarab(''); + +-- Пример: остановить scarab-acc2-05 +SELECT ssot.pause_scarab('scarab-acc2-05'); +``` + +Для полной остановки всего флота: + +```sql +-- Пауза всех 27 сервисов +SELECT ssot.pause_scarab(canon_name) +FROM ssot.scarab_heartbeat +GROUP BY canon_name; +``` + +Для возобновления — через Railway UI/CLI: **Redeploy** соответствующего сервиса. + +> ℹ️ queen-hive-mcp (L-SS3, PR #161) предоставляет полный набор MCP-инструментов +> для управления флотом после деплоя: pause, resume, drain, status. + +--- + +## 9. Ссылки + +| Ресурс | URL | +|--------|-----| +| Epic L-SS | https://github.com/gHashTag/trios/issues/940 | +| Issue L-SS2 | https://github.com/gHashTag/trios-railway/issues/210 | +| L-SS1 (образ) | https://github.com/gHashTag/trios-railway/pull/159 | +| L-SS3 (queen-hive-mcp) | https://github.com/gHashTag/trios-railway/pull/161 | +| PR #214 (deprecated mass-deploy) | https://github.com/gHashTag/trios-railway/pull/214 | +| Railway Docs | https://docs.railway.com | +| GHCR образ | https://ghcr.io/ghashtag/sovereign-scarab | + +--- + +*Документ подготовлен Queen Hive Bot · φ² + φ⁻² = 3* diff --git a/railway.toml.template b/railway.toml.template new file mode 100644 index 00000000..632826fc --- /dev/null +++ b/railway.toml.template @@ -0,0 +1,53 @@ +# railway.toml.template — Sovereign Scarab v4 +# +# Шаблон конфигурации Railway для одного сервиса sovereign-scarab. +# Скопируйте этот файл в корень сервиса и переименуйте в railway.toml, +# заполнив все плейсхолдеры <...>. +# +# Документация: docs/DEPLOY_SOVEREIGN_SCARAB_V4.md +# Issue: https://github.com/gHashTag/trios-railway/issues/210 +# Epic: https://github.com/gHashTag/trios/issues/940 +# Anchor: phi^2 + phi^-2 = 3 + +[build] +# Используем готовый Docker-образ — сборка на Railway не нужна. +builder = "DOCKERFILE" +# Образ задаётся через переменную Railway "Source Image" в UI/CLI: +# ghcr.io/ghashtag/sovereign-scarab:v4 +# Публикуется workflow: .github/workflows/sovereign-scarab.yml (L-SS1, PR #159) + +[deploy] +# Healthcheck через HTTP не используется. +# Мониторинг состояния — heartbeat-строки в ssot.scarab_heartbeat. +healthcheckPath = "" +healthcheckTimeout = 0 +numReplicas = 1 +restartPolicyType = "ON_FAILURE" + +# Переменные окружения (заменить плейсхолдеры реальными значениями перед деплоем): +[deploy.env] + +# --- ОБЯЗАТЕЛЬНЫЕ --- + +# Строка подключения к Trinity SSOT. +# ВАЖНО: должна указывать на единый источник истины (Trinity SSOT), +# не на локальную или тестовую БД. +DATABASE_URL = "postgresql://:@:/" + +# --- ОПЦИОНАЛЬНЫЕ (значения по умолчанию показаны) --- + +# Идентификатор датасета для обучения. +TRAIN_DATA = "fineweb" + +# Интервал опроса очереди задач, миллисекунды. +POLL_INTERVAL_MS = "2000" + +# Интервал записи heartbeat в БД, секунды. +HEARTBEAT_INTERVAL_S = "30" + +# Уровень логирования (structured JSON logs). +RUST_LOG = "info,sovereign_scarab=debug" + +# RAILWAY_SERVICE_ID проставляется Railway автоматически в runtime. +# Явно задавать только при локальном тестировании. +# RAILWAY_SERVICE_ID = ""