Files
orchestrator/docs/architecture/adr/adr-0036-replication-foundation-host-parametrization.md
claude-bot 26bdd783d6
All checks were successful
CI / test (push) Successful in 59s
architect(ET): auto-commit from architect run_id=603
2026-06-10 20:23:50 +03:00

9.6 KiB
Raw Permalink Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-101 architecture architect proposed 2026-06-10 claude-opus-4-8

adr-0036: Фундамент тиража платформы — параметризация хоста, секреты, smoke (ORCH-101, 10-common)

Статус

Proposed

Контекст

Эпик ORCH-10 (D5.3 «Масштаб») — тираж платформы для заказчиков-тестеров двумя типами (A Lite / B Bundled), оба stateless. Платформа была фактически прибита к хосту mva154: четыре места в src/** обходили конфиг (внешний Gitea-URL в plane_sync, HOME + git-идентичности акторов в launcher/self_deploy/post_deploy), docker-compose.yml/Dockerfile/deploy-hook несли литералы путей/uid/gid/портов; механизма выпуска нового комплекта секретов и процедуры верификации развёрнутой копии не существовало. ORCH-101 (10-common) — общий фундамент обоих типов тиража.

Это сквозное решение: оно задаёт платформенные конвенции тиража и трогает блоки, помеченные маркерами ORCH-036/ORCH-040/ORCH-058 (по docs/_standards/TRACEABILITY.md — сводный ADR вместо архео-перечисления). Детальный пакет решений (D1…D10) — work-item ADR: docs/work-items/ORCH-101/06-adr/ADR-001-host-parametrization-secrets-smoke.md.

Решение

Принцип: «дефолт = боевое значение». Каждое хост-специфичное значение читается из конфига (Settings env ORCH_* / compose-интерполяция ${VAR:-default} / Dockerfile ARG / shell-default хука) с дефолтом, равным текущему боевому значению. Отсутствие новых переменных = байт-в-байт текущее поведение (kill-switch-природа; отдельный функциональный флаг не вводится). src/config.py и watchdog/config.py — единственные легитимные места хост-литералов в коде.

Новые конфиг-ключи: agent_home_dir (ORCH_AGENT_HOME_DIR, /home/slin) — HOME всех акторских процессов; agent_git_name (claude-bot) + git_email_domain (mva154.local) — git-идентичности (<actor>@<domain>; системные акторы deploy-finalizer/post-deploy-monitor — платформенные литералы); staging_port (ORCH_STAGING_PORT, 8501). Ссылки в Plane-комментариях — из существующих gitea_public_url/gitea_owner. Compose-слой — карта ORCH_HOST_*/ ORCH_DOCKER_GID/ORCH_RUN_UID/GID + реюз ORCH_DEPLOY_*; порт прод/стейджинг — явные command: с ${ORCH_DEPLOY_PROD_TARGET_PORT:-8500} / ${ORCH_STAGING_PORT:-8501} (CMD образа не трогается — exec-form + init: true сохранены).

Платформенные конвенции тиража (нормативно):

  1. SELF_HOSTING_REPO = "orchestrator" — константа, не конфиг. На ней «empty CSV → self-hosting only» всех *_repos-leaf'ов; конфигурируемость превращала бы опечатку env в активацию деплой-машинерии на чужом репо или тихое выключение всех self-гейтов. Репо платформы в тираже обязан называться orchestrator (REPLICATION.md).
  2. Имена compose-сервисов/контейнеров/образов, профиль staging, network_mode: host, контейнерный layout (/app/data, /repos, /opt/claude-code) — конвенции, не переменные (для образов истина уже в конфиге deploy_prod_*_image).
  3. Staging-порт конфигурируем ТОЛЬКО с fail-closed guard'ом (усиление инварианта ORCH-058 AC-9): freshness-путь отказывает ДО любого ssh/build при staging_port == deploy_prod_target_port — без тихого fallback. Explicit-pass таргета хуку (TARGET_PORT= и др.) сохранён; добавлена явная передача REPO= обоими инвокерами хука (его строка 38 становится "${REPO:-…}" — exit-контракт 0/1/2 ORCH-036 не тронут).
  4. Группа ORCH-040 неделима: uid/gid/HOME/маунт-таргеты/useradd управляются одними env насквозь (ORCH_RUN_UID/GID, ORCH_AGENT_HOME_DIR → compose user:/таргеты/build.args APP_*); group_add docker-gid («МИНА 1») не удаляется — литерал станет ${ORCH_DOCKER_GID:-999}.

Секреты нового хоста: stdlib-скрипт scripts/gen_secrets.py — криптослучайные webhook-секреты (secrets.token_hex(32)), печать по умолчанию, --write отказывает при существующем .env (перезапись — только явный --force); внешние токены (Plane/Gitea/Telegram/watchdog) — по чек-листу. Норматив: боевые секреты текущего хоста не копируются ни на одном шаге.

Smoke-верификация тиража: runbook docs/operations/REPLICATION.md (deployment golden source: карта env, чек-лист секретов, пошаговый smoke с PASS/FAIL: compose config/health/queue+/metricsonboard_project.py plan/apply/verify → тестовая задача → артефакты 0104 в ветке; расширенно — до done; границы 10-common vs Lite vs Bundled). Нового smoke-скрипта нет — шаги собраны из существующих кирпичей.

Анти-регресс (постоянная CI-гарантия): структурный сканер tests/test_no_host_hardcodes.py — запрещённые литералы (82.22.50.71, /home/slin, mva154, duckdns; список централизован) в исполняемом коде src/**+watchdog/**; tokenize-исключение комментариев/докстрингов; структурное исключение двух config-модулей (канон дефолтов); allowlist пуст; негативная самопроверка.

Что НЕ меняется

STAGE_TRANSITIONS, состав QG_CHECKS, семантика check_*, machine-verdict ключи, схема БД — байт-в-байт; значения существующих конфиг-дефолтов; INV-4; прод-контейнер в рамках задачи не рестартуется (правки compose/Dockerfile инертны до штатного деплоя через staging 8501 → Confirm Deploy).

Альтернативы

  • ORCH_SELF_HOSTING_REPO конфигом — отвергнуто: узел безопасности; опечатка = групповой риск.
  • Staging-порт константой — отвергнуто: compose-порт параметризуется (AC-6), константа дала бы рассинхрон слоёв; пара «ключ + guard» строго сильнее.
  • Smoke-скрипт-обвязка / генератор в onboard_project.py — отвергнуто: лишняя поверхность; разные жизненные циклы (онбординг проекта ≠ provisioning хоста).

Последствия

  • Платформа разворачивается на чужой инфре env-конфигурацией; критический путь ORCH-10 разблокирован (Lite/Bundled строятся поверх REPLICATION.md).
  • Инвариант ORCH-058 переходит из «подразумеваемого константой» в исполняемый guard; возврат хост-хардкода ломает CI структурно.
  • Цена: ~13 новых env-имён (на текущем хосте настраивать нечего — дефолты боевые) и правило «интерполяция читает .env/shell, не env_file» (зафиксировано в REPLICATION.md).
  • Откат: не задавать переменные (дефолты = прежнее поведение); полный — revert PR (без миграций).

Связи

adr-0005 (ORCH-040 — uid/HOME/«МИНА 1»; группа становится параметризуемой, инвариант сохранён), adr-0008 (ORCH-058 — INV-FRESH/AC-9; guard усиливает), adr-0007 (ORCH-036 — exit-контракт хука не тронут), adr-0035 (ORCH-009 — onboarding переиспользуется smoke-процедурой; kit не форкается), adr-0001 (is_self_hosting_repo — конвенция имени закреплена). Детально — docs/work-items/ORCH-101/06-adr/ADR-001-host-parametrization-secrets-smoke.md (D1…D10), 07-infra-requirements.md, 10-tech-risks.md.