feat(replication): ORCH-10b Bundled-тираж — bundle-compose всего стека + bootstrap-скрипт

Закрывает Type B эпика ORCH-10 (по ADR-001 ORCH-103, D1–D11):

- deploy/bundled/docker-compose.yml — самодостаточный compose всего стека
  (орк + watchdog + Gitea 1.22.6 + зеркало upstream Plane CE v0.23.1,
  ~14 контейнеров); project name orchestrator-bundle (узнаваемый префикс),
  container_name не пиннится, staging-контура нет; одна bridge-сеть,
  машинный трафик — сервис-DNS, наружу только человеческие порты;
  GITEA__webhook__ALLOWED_HOST_LIST=orchestrator; все образы пиннованы
  неподвижными тегами. Корневой compose/Dockerfile/src/** — байт-в-байт.
- deploy/bundled/.env.example — конфиг-канон bundle (плейсхолдеры, ни одного
  дефолтного пароля; key-set-sync интерполяций держит тест).
- scripts/bootstrap_bundle.py — python stdlib-only, режимы plan/apply/verify,
  step-движок check→ensure, exit 0/2/1: preflight (fail-fast до мутаций) →
  секреты (gen_secrets.py + stdlib secrets, без перетирания) → up+готовность →
  init Gitea автоматом → init Plane (manual-step с API-верификацией) →
  онбординг строго onboard_project.py apply+verify → token-remote клон →
  сборка .env/.env.watchdog (единственный писатель, права 600) → health.
  Delete-операций нет вообще (D9), секреты не печатаются (NFR-3).
- CHANGELOG.md, CLAUDE.md (абзац Type B), .gitignore (deploy/bundled/repos/).

Док BUNDLED_SETUP.md, REPLICATION §1, arch README, adr-0038 и три структурных
тест-модуля (TC-01…TC-11) — в предыдущих коммитах ветки; полный регресс
1844 passed, ruff по файлам задачи чистый.

Refs: ORCH-103

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 02:01:50 +03:00
committed by orchestrator-deployer
parent 215930fb90
commit f0cd19d748
7 changed files with 1411 additions and 2 deletions

View File

@@ -0,0 +1,61 @@
# deploy/bundled/.env — конфиг bundle-ИНФРЫ (ORCH-103, ADR-001 D2).
# Канонический example: 100% ключей интерполяции deploy/bundled/docker-compose.yml
# (key-set-sync держит tests/test_bundle_compose.py) + ключи init-кред, которые
# заполняет bootstrap. Создание: cp .env.example .env (или это сделает
# scripts/bootstrap_bundle.py apply); права 600.
#
# ⚠️ СЕМАНТИКА ФАЙЛА-НОСИТЕЛЯ (TR-8): этот файл читает ТОЛЬКО compose-интерполяция
# bundle (авто-чтение .env из project dir deploy/bundled/). Runtime-конфиг самого
# оркестратора и watchdog — КОРНЕВЫЕ .env / .env.watchdog (каноны Lite 1:1:
# .env.example / .env.watchdog.example, карта — docs/operations/REPLICATION.md §2).
# Единственный писатель всех live-файлов — scripts/bootstrap_bundle.py: дублируемые
# ключи (uid/gid, HOME, пути Claude CLI) когерентны механически, не дисциплиной.
#
# DO NOT COMMIT реальный deploy/bundled/.env (покрыт неякорным `.env` в .gitignore).
# Секреты: НИ ОДНОГО дефолтного пароля — пустые значения ниже генерирует bootstrap
# (stdlib secrets) и никогда не печатает (NFR-3); повторный запуск НЕ перетирает
# существующие значения без явного --force-secrets.
# --- Публичная точка инсталляции -------------------------------------------
# Хост, по которому браузер оператора открывает Plane/Gitea и по которому
# строятся публичные ссылки (ORCH_GITEA_PUBLIC_URL / ORCH_PLANE_WEB_URL / WEB_URL
# Plane / ROOT_URL Gitea). HTTPS/домены/reverse-proxy заказчика — вне bundle.
BUNDLE_PUBLIC_HOST=localhost
# --- Карта публикуемых портов (D4: только человеческие точки) ---------------
# Конфликт порта на хосте → отказ preflight bootstrap ДО любых мутаций (BR-7).
BUNDLE_ORCH_PORT=8500
BUNDLE_PLANE_PORT=8080
BUNDLE_GITEA_HTTP_PORT=3000
# --- Идентичность контейнера орка (реюз имён ORCH-101: один факт = одно имя) --
# uid:gid владельца deploy/bundled/repos (инвариант ORCH-040); docker-gid хоста
# («МИНА 1», узнать: getent group docker). Заполняет bootstrap из id -u/-g/getent.
ORCH_RUN_UID=1000
ORCH_RUN_GID=1000
ORCH_DOCKER_GID=999
# HOME всех акторов в контейнере (группа ORCH-040 двигается одной переменной).
ORCH_AGENT_HOME_DIR=/home/orchestrator
# --- LLM-предусловие хоста заказчика (bundle НЕ поставляет Claude CLI) -------
# Пути дистрибутива claude-code/node и кред CLI на хосте (канон — LITE_SETUP §7).
ORCH_HOST_CLAUDE_CODE_DIR=/usr/lib/node_modules/@anthropic-ai/claude-code
ORCH_HOST_NODE_BIN=/usr/bin/node
ORCH_HOST_CLAUDE_DIR=~/.claude
ORCH_HOST_CLAUDE_JSON=~/.claude.json
# --- Внутренние креды Plane CE-стека (upstream-имена; значения — bootstrap) --
POSTGRES_USER=plane
POSTGRES_PASSWORD=
POSTGRES_DB=plane
SECRET_KEY=
RABBITMQ_DEFAULT_USER=plane
RABBITMQ_DEFAULT_PASS=
RABBITMQ_DEFAULT_VHOST=plane
MINIO_ROOT_USER=plane-minio-admin
MINIO_ROOT_PASSWORD=
# --- Init-креды Gitea (D6: один пользователь-бот = админ, владелец репо,
# носитель API-токена; создаёт bootstrap через `gitea admin user create`) --
GITEA_ADMIN_USERNAME=orchestrator-bot
GITEA_ADMIN_PASSWORD=