437 lines
23 KiB
Markdown
437 lines
23 KiB
Markdown
# BUNDLED_SETUP — Bundled-тираж: весь стек одним комплектом (ORCH-103)
|
||
|
||
> **Golden source Bundled-тиража (Type B эпика ORCH-10).** Маршрут «чистый хост →
|
||
> работающий конвейер» для заказчика **без собственной инфраструктуры**: один
|
||
> compose-комплект (`deploy/bundled/docker-compose.yml`) поднимает оркестратор +
|
||
> watchdog + Gitea + Plane CE, один запуск `scripts/bootstrap_bundle.py apply`
|
||
> доводит стек до рабочего состояния. Каждый шаг — исполняемая команда + явная
|
||
> проверка результата (**Проверка:** / PASS / FAIL). Хост-специфика — только
|
||
> плейсхолдеры `<...>` и `$ENV_VAR`. Тираж **stateless**: данные/задачи/секреты
|
||
> боевого (исходного) хоста **НЕ переносятся** ни на одном шаге (§12).
|
||
> Границы слоёв тиража (10-common vs Lite vs Bundled) — `docs/operations/REPLICATION.md` §1;
|
||
> канон Lite (своя инфраструктура Plane/Gitea) — `docs/deployment/LITE_SETUP.md`.
|
||
|
||
---
|
||
|
||
## 1. Рамка Bundled
|
||
|
||
**Что входит в комплект** (compose-проект `orchestrator-bundle`, одна bridge-сеть):
|
||
- `orchestrator` (конвейер, образ собирается из этого чекаута) и
|
||
`orchestrator-watchdog` (независимый sidecar-мониторинг);
|
||
- **Gitea** (git-хостинг, пиннованный официальный образ);
|
||
- **Plane CE — ≈ 14 контейнеров** (зеркало официального selfhost-комплекта:
|
||
web/space/admin/api/worker/beat-worker/migrator/live + postgres/redis/
|
||
rabbitmq/minio/proxy) — это **ресурсоёмко**, см. §2.
|
||
|
||
**Что НЕ входит** (внешние предусловия заказчика):
|
||
- **Claude CLI / LLM-доступ** — дистрибутив claude-code, node и аутентификация
|
||
живут на хосте и пробрасываются маунтами (§8); без них стек поднимется, но
|
||
конвейер не поедет;
|
||
- **Telegram-боты** — опциональны (§9): пусто = деградация только нотификаций;
|
||
- **HTTPS/домены/reverse-proxy** — вне bundle: наружу публикуются три http-порта
|
||
(§2), терминирование TLS — средствами заказчика.
|
||
|
||
**Bundled vs Lite:** Lite (`LITE_SETUP.md`) подключает оркестратор к **вашим**
|
||
Plane/Gitea; Bundled везёт их **с собой** на чистых томах. Staging-контур орка в
|
||
bundle отсутствует вовсе: заказчик Type B эксплуатирует платформу для своих
|
||
проектов, а не развивает её self-hosting'ом (нужен self-hosting — маршрут Lite,
|
||
`LITE_SETUP.md` §9.3). Репо `orchestrator` в bundle-инсталляции **не
|
||
регистрируется** как проект.
|
||
|
||
**Осознанный компромисс (TR-7):** git-доступ агентов — HTTP token-remote
|
||
(токен бот-юзера в конфиге локальных чекаутов, права 600); ssh-контур
|
||
сознательно не вводится; порты БД/брокера/minio наружу не публикуются.
|
||
|
||
---
|
||
|
||
## 2. Требования к хосту
|
||
|
||
Linux x86_64, один хост. Минимумы проверяет preflight bootstrap **до любых
|
||
мутаций** (пороги — константы `scripts/bootstrap_bundle.py`, ниже — те же цифры;
|
||
подтверждаются замером приёмочного развёртывания):
|
||
|
||
| Ресурс | Минимум | Почему |
|
||
|--------|---------|--------|
|
||
| RAM | **8 GB** | Plane CE — ≈ 14 контейнеров (миграции и брокер прожорливы) |
|
||
| Диск | **40 GB** свободно | образы стека + тома postgres/minio/gitea + данные орка |
|
||
| CPU | **4 vCPU** (рекомендация) | меньше — стек поднимется, но будет медленным |
|
||
|
||
**Карта публикуемых портов** (дефолты; конфигурируемы в
|
||
`deploy/bundled/.env`, ключи `BUNDLE_*`):
|
||
|
||
| Порт | Ключ | Сервис |
|
||
|------|------|--------|
|
||
| 8500 | `BUNDLE_ORCH_PORT` | API оркестратора (`/health`, `/queue`, `/metrics`, вебхуки) |
|
||
| 8080 | `BUNDLE_PLANE_PORT` | Plane UI (proxy) |
|
||
| 3000 | `BUNDLE_GITEA_HTTP_PORT` | Gitea web/API |
|
||
|
||
Postgres/redis/rabbitmq/minio наружу **не публикуются** (машинный трафик —
|
||
внутрисетевой сервис-DNS).
|
||
|
||
```bash
|
||
free -g # RAM ≥ 8 GB
|
||
df -h . # свободно ≥ 40 GB
|
||
nproc # ≥ 4
|
||
ss -ltn | grep -E ':(8500|8080|3000)\b' || echo "ports free"
|
||
```
|
||
|
||
**Проверка:** ресурсы не ниже минимумов и `ports free` — PASS. Порт занят →
|
||
смените соответствующий `BUNDLE_*`-ключ в §5 (или освободите порт) — иначе
|
||
preflight откажет (FAIL до мутаций, это штатно).
|
||
|
||
---
|
||
|
||
## 3. Предусловия
|
||
|
||
Софт хоста: Docker Engine + Compose v2, git, python3 (+venv), sudo у оператора.
|
||
|
||
```bash
|
||
uname -sm # Linux x86_64
|
||
docker --version && docker compose version
|
||
git --version && python3 --version
|
||
python3 -m venv --help >/dev/null && echo "venv: ok"
|
||
getent group docker # третье поле — gid, понадобится в §5 (ORCH_DOCKER_GID)
|
||
id -u && id -g # uid/gid оператора (ORCH_RUN_UID / ORCH_RUN_GID)
|
||
```
|
||
|
||
**Проверка:** все команды отвечают без ошибок, gid группы docker известен —
|
||
PASS; что-то отсутствует — FAIL (доставьте пакет средствами дистрибутива).
|
||
|
||
---
|
||
|
||
## 4. Получение кода
|
||
|
||
Переносится **только код** — чекаут репо `orchestrator` (норматив §12).
|
||
|
||
```bash
|
||
git clone <ORCHESTRATOR_GIT_URL> <путь-чекаута>
|
||
cd <путь-чекаута>
|
||
ls deploy/bundled/docker-compose.yml deploy/bundled/.env.example \
|
||
scripts/bootstrap_bundle.py scripts/gen_secrets.py scripts/onboard_project.py
|
||
```
|
||
|
||
**Проверка:** все пять файлов на месте — PASS. Канал дистрибуции
|
||
(`<ORCHESTRATOR_GIT_URL>`) согласуйте с поставщиком платформы (как в
|
||
`LITE_SETUP.md` §3).
|
||
|
||
---
|
||
|
||
## 5. Секреты
|
||
|
||
Все секреты инсталляции выпускаются **заново на месте** (§12): webhook-секреты —
|
||
`scripts/gen_secrets.py`, внутренние креды Plane/Gitea-стека — генерирует
|
||
bootstrap (в репо — только пустые плейсхолдеры, ни одного дефолтного пароля).
|
||
|
||
**5.1. Конфиг bundle-инфры.**
|
||
|
||
```bash
|
||
cd <путь-чекаута>
|
||
cp deploy/bundled/.env.example deploy/bundled/.env
|
||
chmod 600 deploy/bundled/.env
|
||
# заполнить НЕсекретные ключи: BUNDLE_PUBLIC_HOST (IP/имя хоста для браузера),
|
||
# карту портов BUNDLE_* (§2), ORCH_RUN_UID/ORCH_RUN_GID (из §3),
|
||
# ORCH_DOCKER_GID (getent group docker, §3), пути Claude CLI (§8).
|
||
```
|
||
|
||
**Проверка:**
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml config --quiet && echo "config: PASS"
|
||
```
|
||
|
||
`config: PASS` — интерполяция согласована; ошибка — FAIL (опечатка в
|
||
`deploy/bundled/.env`).
|
||
|
||
**5.2. Секрет-значения** (пустые ключи `deploy/bundled/.env` и корневого `.env`)
|
||
заполнит `bootstrap_bundle.py apply` (§7): webhook-секреты — субпроцессом
|
||
`gen_secrets.py`, креды postgres/rabbitmq/minio/`SECRET_KEY` Plane и пароль
|
||
админ-бота Gitea — stdlib-генератором. Значения **не печатаются** (только имена
|
||
ключей); повторный запуск **не перетирает** существующие секреты (явная
|
||
регенерация — флаг `--force-secrets`, допустим только ДО первого запуска стека).
|
||
|
||
```bash
|
||
grep -cE '^(POSTGRES_PASSWORD|SECRET_KEY|RABBITMQ_DEFAULT_PASS|MINIO_ROOT_PASSWORD|GITEA_ADMIN_PASSWORD)=$' \
|
||
deploy/bundled/.env
|
||
```
|
||
|
||
**Проверка:** до §7 счётчик `5` (пустые плейсхолдеры) — PASS; после §7 — `0`.
|
||
|
||
---
|
||
|
||
## 6. Запуск bundle-compose
|
||
|
||
Одна команда поднимает весь стек (≈ 16 контейнеров; первый запуск тянет образы
|
||
и гоняет миграции Plane — это минуты, не секунды).
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml up -d
|
||
docker compose -f deploy/bundled/docker-compose.yml ps
|
||
```
|
||
|
||
**Проверка:** все сервисы в состоянии `Up`/`Up (healthy)`; `migrator` —
|
||
`Exited (0)` (одноразовая миграция) — PASS. Контейнер в рестарт-цикле — FAIL
|
||
(§14). Шаг идемпотентен; можно пропустить — `bootstrap_bundle.py apply` выполнит
|
||
`up -d` сам (§7).
|
||
|
||
---
|
||
|
||
## 7. Bootstrap
|
||
|
||
Доводка «одним запуском»: preflight → секреты → up/готовность → init Gitea
|
||
(полностью автоматом: админ-бот + API-токен) → init Plane → онбординг
|
||
sandbox-проекта **строго** кирпичом `onboard_project.py` (22 канонических
|
||
статуса, включая fail-closed **`Confirm Deploy`** и **`STOP`**, лейблы,
|
||
репо+webhook — golden source `docs/operations/ONBOARDING.md` §1) → git-доступ
|
||
агентов → сборка `.env`/`.env.watchdog` → health.
|
||
|
||
```bash
|
||
python3 scripts/bootstrap_bundle.py # план + preflight-диагностика (ноль мутаций)
|
||
python3 scripts/bootstrap_bundle.py apply # полный прогон
|
||
```
|
||
|
||
**Manual-step чекпоинты Plane CE** (API первичной инициализации в CE нет;
|
||
каждый чекпоинт: точная инструкция → подтверждение → верификация результата
|
||
API-пробой, молчаливый пропуск запрещён):
|
||
1. **instance setup** — открыть Plane UI, зарегистрировать первого
|
||
пользователя (станет администратором инстанса);
|
||
2. **workspace** — создать workspace, ввести его slug в bootstrap;
|
||
3. **API-токен** — Workspace Settings → API tokens, вставить значение в
|
||
bootstrap (ввод скрыт; уходит в `ORCH_PLANE_API_TOKEN`);
|
||
4. **workspace-webhook** — bootstrap регистрирует сам (запись в Postgres
|
||
инсталляции, путь Б канона `LITE_SETUP.md` §5.4) и проверяет; при отказе —
|
||
честный ручной шаг с той же проверкой;
|
||
5. **порядок статусов на доске** — drag-and-drop по отчёту onboard
|
||
(`docs/operations/ONBOARDING.md`).
|
||
|
||
Exit-коды: `0` — успех; `2` — остановка на manual-step/предусловии (выполните
|
||
шаг и перезапустите `apply` — завершённые шаги пропускаются, повторный запуск
|
||
безопасен); `1` — ошибка. Пароль админ-бота Gitea — ключ `GITEA_ADMIN_PASSWORD`
|
||
в `deploy/bundled/.env` (права 600; вход в UI Gitea под
|
||
`GITEA_ADMIN_USERNAME`).
|
||
|
||
**Проверка:**
|
||
|
||
```bash
|
||
python3 scripts/bootstrap_bundle.py verify && echo "bootstrap: PASS"
|
||
```
|
||
|
||
`verify` зелёный (health/queue/metrics + onboard verify) — PASS; exit 2 —
|
||
остались ручные пункты отчёта; exit 1 — FAIL (§14).
|
||
|
||
---
|
||
|
||
## 8. LLM (claude CLI)
|
||
|
||
Канон — `LITE_SETUP.md` §7 (полностью применим; не дублируется). Кратко: на
|
||
хост ставятся claude-code + node, выполняется интерактивный логин CLI; пути
|
||
прописываются в `deploy/bundled/.env` (это источники маунтов контейнера орка):
|
||
`ORCH_HOST_CLAUDE_CODE_DIR`, `ORCH_HOST_NODE_BIN`, `ORCH_HOST_CLAUDE_DIR`,
|
||
`ORCH_HOST_CLAUDE_JSON`.
|
||
|
||
```bash
|
||
claude --version
|
||
docker compose -f deploy/bundled/docker-compose.yml exec orchestrator /usr/bin/claude --version
|
||
```
|
||
|
||
**Проверка:** обе команды печатают версию — PASS; вторая падает — пути в
|
||
`deploy/bundled/.env` не указывают на фактические каталоги хоста (§14.4).
|
||
|
||
---
|
||
|
||
## 9. Telegram
|
||
|
||
Канон — `LITE_SETUP.md` §8 (два независимых бота, C-1: токен орка для watchdog
|
||
переиспользовать запрещено). Ключи орка (`ORCH_TELEGRAM_BOT_TOKEN`,
|
||
`ORCH_TELEGRAM_CHAT_ID`) — в корневой `.env`; ключи watchdog
|
||
(`WATCHDOG_TG_BOT_TOKEN`, `WATCHDOG_TG_CHAT_ID`) — **только** в `.env.watchdog`
|
||
(файл-носитель, `LITE_SETUP.md` §4.3). Шаг опционален: пустые токены =
|
||
деградация только нотификаций.
|
||
|
||
```bash
|
||
grep -E '^ORCH_TELEGRAM_(BOT_TOKEN|CHAT_ID)=' .env
|
||
grep -E '^WATCHDOG_TG_(BOT_TOKEN|CHAT_ID)=' .env.watchdog
|
||
docker compose -f deploy/bundled/docker-compose.yml up -d orchestrator orchestrator-watchdog
|
||
```
|
||
|
||
**Проверка:** ключи заполнены и контейнеры пересозданы → тестовое сообщение от
|
||
обоих ботов (`getMe` — команды в `LITE_SETUP.md` §8) — PASS; пусто — осознанный
|
||
PASS без нотификаций.
|
||
|
||
---
|
||
|
||
## 10. Онбординг следующих проектов
|
||
|
||
Sandbox-проект создал bootstrap (§7). Каждый следующий проект заказчика —
|
||
штатный runbook `docs/operations/ONBOARDING.md` поверх bundle-инсталляции; для
|
||
команд из чекаута: Plane/Gitea доступны на `localhost`-портах §2, webhook-URL —
|
||
in-network `http://orchestrator:8500/webhook/gitea`.
|
||
|
||
```bash
|
||
. .venv/bin/activate # venv создан bootstrap'ом (§7)
|
||
python3 scripts/onboard_project.py plan \
|
||
--name "<имя проекта>" --repo <repo> --prefix <PREFIX> \
|
||
--stack "<стек>" --test-cmd "<команда тестов>" \
|
||
--prod-port <порт-прода> --staging-port <порт-staging> \
|
||
--webhook-url http://orchestrator:8500/webhook/gitea
|
||
# план устроил → apply → verify (как в LITE_SETUP.md §10), затем:
|
||
# строку ORCH_PROJECTS_JSON из отчёта — в .env и пересоздать орк:
|
||
docker compose -f deploy/bundled/docker-compose.yml up -d --force-recreate orchestrator
|
||
```
|
||
|
||
**Проверка:** `verify` зелёный; `GET /queue` отвечает после пересоздания — PASS.
|
||
|
||
---
|
||
|
||
## 11. Smoke
|
||
|
||
Процедура — чек-лист `docs/operations/REPLICATION.md` §4 (шаги 0–5; шаг 6 «до
|
||
`done`» — опционально) поверх bundle-инсталляции, без форка. Минимальный сигнал
|
||
«конвейер доехал»: issue в sandbox-проекте Plane → статус **To Analyse** →
|
||
артефакты `01`–`04` в ветке задачи.
|
||
|
||
```bash
|
||
curl -fsS http://127.0.0.1:8500/health
|
||
curl -fsS http://127.0.0.1:8500/queue | python3 -m json.tool | head -30
|
||
curl -fsS http://127.0.0.1:8500/metrics | python3 -m json.tool | head -10
|
||
# создать issue в Plane (порт 8080) → перевести в «To Analyse», затем:
|
||
curl -fsS http://127.0.0.1:8500/queue | python3 -m json.tool | head -40 # job появился
|
||
git -C deploy/bundled/repos/sandbox fetch origin
|
||
git -C deploy/bundled/repos/sandbox ls-tree --name-only origin/<ветка-задачи> "docs/work-items/<id>/"
|
||
```
|
||
|
||
**Проверка:** оба направления связности живы — job в `/queue` (Plane→орк
|
||
доехал), `ls-tree` показывает `01-brd.md` … `04-test-plan.yaml` (орк→Gitea
|
||
пишет; Gitea→орк события идут) — PASS. Любой шаг FAIL → тираж FAIL: соберите
|
||
`docker compose -f deploy/bundled/docker-compose.yml logs --tail 100 orchestrator`
|
||
и снапшот `GET /queue`, разбор — §14. (Порты замените, если меняли `BUNDLE_*`.)
|
||
|
||
---
|
||
|
||
## 12. Stateless-проверка
|
||
|
||
**Нормативно: данные/задачи/секреты/БД боевого (исходного) хоста НЕ
|
||
переносятся** (зеркало `docs/operations/REPLICATION.md` §5). Все тома bundle
|
||
созданы заново при первом `up`; секреты — только свежевыпущенные (§5); в
|
||
Plane/Gitea инсталляции нет чужих задач/репо/пользователей.
|
||
|
||
```bash
|
||
docker volume ls --format '{{.Name}}' | grep '^orchestrator-bundle' # только тома этой инсталляции
|
||
curl -fsS http://127.0.0.1:8500/queue | python3 -m json.tool # счётчики нулевые
|
||
```
|
||
|
||
**Проверка:** в `/queue` нулевые счётчики и ни одной чужой задачи (никаких
|
||
work-item исходного хоста) — PASS. Чужая задача/перенесённый файл БД — FAIL:
|
||
инсталляция собрана не stateless, выполните полный сброс (§13) и повторите.
|
||
|
||
---
|
||
|
||
## 13. Остановка и полный сброс
|
||
|
||
Teardown — **только эта документированная процедура** (в bootstrap delete-режима
|
||
сознательно нет, ADR-001 D9).
|
||
|
||
**Остановка (обратимая):**
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml down
|
||
```
|
||
|
||
**Проверка:** `docker compose -f deploy/bundled/docker-compose.yml ps` пуст;
|
||
тома целы (`docker volume ls | grep orchestrator-bundle`) — PASS.
|
||
|
||
**Полный сброс (НЕОБРАТИМО — удаляет все данные Plane/Gitea/орка):**
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml down -v
|
||
rm -rf deploy/bundled/data deploy/bundled/repos
|
||
rm -f deploy/bundled/.env .env .env.watchdog
|
||
```
|
||
|
||
**Проверка:** `docker volume ls --format '{{.Name}}' | grep -c '^orchestrator-bundle'`
|
||
→ `0`; live-конфигов нет — PASS (хост чист, можно разворачивать заново с §5).
|
||
|
||
---
|
||
|
||
## 14. Траблшутинг
|
||
|
||
Формат: симптом → диагностика → лечение.
|
||
|
||
**14.1. Webhook не доходит (issue в Plane есть, job в `/queue` нет).**
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml logs --tail 50 orchestrator | grep -i "webhook\|signature"
|
||
docker compose -f deploy/bundled/docker-compose.yml exec -T plane-db \
|
||
psql -U plane -d plane -c "SELECT url, is_active FROM webhooks;"
|
||
```
|
||
|
||
Лечение: (а) нет строки webhook → §7 чекпоинт 4; (б) URL не
|
||
`http://orchestrator:8500/webhook/plane` → исправьте на in-network URL;
|
||
(в) 401/HMAC → секрет в Plane обязан байт-в-байт совпадать с
|
||
`ORCH_PLANE_WEBHOOK_SECRET` корневого `.env`. Для Gitea-направления проверьте
|
||
Recent Deliveries в настройках hook'а репо; помните про
|
||
`GITEA__webhook__ALLOWED_HOST_LIST=orchestrator` в bundle-compose (без него
|
||
Gitea молча режет вебхуки в приватные адреса).
|
||
|
||
**14.2. Не хватает RAM / OOM (контейнеры Plane в рестарт-цикле).**
|
||
|
||
```bash
|
||
free -g && docker stats --no-stream | head -20
|
||
docker compose -f deploy/bundled/docker-compose.yml ps
|
||
```
|
||
|
||
Лечение: минимум §2 (8 GB; Plane ≈ 14 контейнеров). Меньше — добавьте RAM/swap;
|
||
preflight bootstrap отказывает заранее именно поэтому.
|
||
|
||
**14.3. Порт занят (`up` падает с bind error).**
|
||
|
||
```bash
|
||
ss -ltnp | grep -E ':(8500|8080|3000)\b'
|
||
```
|
||
|
||
Лечение: смените `BUNDLE_ORCH_PORT`/`BUNDLE_PLANE_PORT`/`BUNDLE_GITEA_HTTP_PORT`
|
||
в `deploy/bundled/.env` и повторите `up`/bootstrap.
|
||
|
||
**14.4. claude не найден / агент падает на старте.**
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml exec orchestrator /usr/bin/claude --version
|
||
ls "$(grep '^ORCH_HOST_CLAUDE_CODE_DIR=' deploy/bundled/.env | cut -d= -f2)"
|
||
```
|
||
|
||
Лечение: пути `ORCH_HOST_*` в `deploy/bundled/.env` обязаны указывать на
|
||
фактические каталоги хоста; креды CLI читаемы uid'ом `ORCH_RUN_UID` (канон —
|
||
`LITE_SETUP.md` §7/§13.3); после правки — `up -d --force-recreate orchestrator`.
|
||
|
||
**14.5. Миграции Plane не завершились (bootstrap падает на ожидании).**
|
||
|
||
```bash
|
||
docker compose -f deploy/bundled/docker-compose.yml logs --tail 50 migrator plane-db
|
||
docker compose -f deploy/bundled/docker-compose.yml ps plane-db plane-mq plane-redis
|
||
```
|
||
|
||
Лечение: чаще всего — нехватка RAM/диска (§14.2) или невыпущенные секреты
|
||
(пустой `POSTGRES_PASSWORD` → postgres не стартует; прогоните §7, который
|
||
заполняет креды ДО `up`). После лечения — повторный `apply` (идемпотентен).
|
||
|
||
**14.6. PR задачи не мержится / HOLD.** Branch protection на `main` в Gitea
|
||
**НЕ включать** — норматив `LITE_SETUP.md` §6.4 (ломает PR-merge API
|
||
merge-актора); bundle-Gitea конфигурируется тем же правилом.
|
||
|
||
```bash
|
||
curl -fsS -H "Authorization: token $ORCH_GITEA_TOKEN" \
|
||
"http://127.0.0.1:3000/api/v1/repos/<owner>/<repo>/branch_protections" | python3 -m json.tool
|
||
```
|
||
|
||
Лечение: непустой список правил → удалить (канон `LITE_SETUP.md` §6.4/§13.7).
|
||
|
||
---
|
||
|
||
*Golden source Bundled-тиража (ORCH-103, ADR-001 D10). **Норматив сопровождения
|
||
(NFR-5):** меняешь шаги Bundled-тиража (состав bundle-compose, ключи
|
||
`deploy/bundled/.env.example`, шаги bootstrap, smoke) → обнови этот док В ТОМ ЖЕ
|
||
PR. Полноту и гигиену держит `tests/test_bundled_setup_doc.py`; кирпичи-каноны:
|
||
`LITE_SETUP.md` (§5–§8 — подключения), `docs/operations/ONBOARDING.md` (статусы
|
||
§1, онбординг), `docs/operations/REPLICATION.md` (карта env §2, секреты §3,
|
||
smoke §4), `deploy/bundled/.env.example` + `.env.example` /
|
||
`.env.watchdog.example` (каноны ключей).*
|