From 1e812b0ba78895ab17425ec7f100eec8fa2f314e Mon Sep 17 00:00:00 2001 From: claude-bot Date: Thu, 11 Jun 2026 02:10:40 +0300 Subject: [PATCH] reviewer(ET): auto-commit from reviewer run_id=629 --- docs/work-items/ORCH-103/12-review.md | 160 ++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 docs/work-items/ORCH-103/12-review.md diff --git a/docs/work-items/ORCH-103/12-review.md b/docs/work-items/ORCH-103/12-review.md new file mode 100644 index 0000000..6509ff1 --- /dev/null +++ b/docs/work-items/ORCH-103/12-review.md @@ -0,0 +1,160 @@ +--- +verdict: APPROVED +work_item: ORCH-103 +stage: review +author_agent: reviewer +status: approved +created_at: 2026-06-11 +model_used: claude-opus-4-8 +type: review +work_item_id: ORCH-103 +version: 1 +--- + +# Review ORCH-103 — ORCH-10b Bundled-тираж: весь стек одним комплектом + bootstrap-скрипт + +> Машинный вердикт читается ТОЛЬКО из `verdict:` во frontmatter. + +## Summary + +PR закрывает Type B эпика ORCH-10 строго по ТЗ и ADR-001 (D1–D11): новый каталог +`deploy/bundled/` (самодостаточный compose 16 сервисов, project name `orchestrator-bundle`, +пиннинг неподвижными тегами, одна bridge-сеть, только человеческие порты, мина +`GITEA__webhook__ALLOWED_HOST_LIST` закрыта), `scripts/bootstrap_bundle.py` (stdlib-only, +`plan`-дефолт/`apply`/`verify`, step-движок check→ensure, exit 0/2/1, ноль delete-операций), +конфиг-канон `deploy/bundled/.env.example` (ни одного дефолтного пароля), +`docs/deployment/BUNDLED_SETUP.md` (14 разделов канона D10) и три содержательных +анти-дрейф тест-модуля. Рантайм байт-в-байт: `git diff main` не содержит `src/**`, +корневого `docker-compose.yml`, `Dockerfile`, `.gitea/workflows/**` (AC-6 подтверждён +diff-stat'ом). Полный регресс: **`pytest tests/ -q` → 1844 passed, 0 failed** (AC-5); +существующие анти-дрейф тесты (`test_lite_setup_doc.py`, `test_no_host_hardcodes.py`, +канон ORCH-009) не правились. Документация обновлена в том же PR по всем точкам §8 ТЗ. +Findings — только P2/P3, блокеров нет → **APPROVED**. + +## Оси проверки + +### 1. Соответствие ТЗ (02-trz.md, 03-acceptance-criteria.md) + +- **FR-1** ✅ — отдельный bundle-compose; состав = ADR D1/D3 (тест + `test_bundle_has_exactly_the_adr_service_set` фиксирует множество); пиннинг всех сторонних + образов литералом (TC-03); тома — именованные с префиксом проекта + bind строго внутри + project dir (TC-04); достижимость в обе стороны — сервис-DNS (D4) + `ALLOWED_HOST_LIST`; + карта портов в доке §2, конфликт порта → отказ preflight; staging-контура нет вовсе. +- **FR-2** ✅ — последовательность шагов 1–9 ТЗ воспроизведена 1:1 в `APPLY_STEPS` + (тест `test_apply_steps_match_normative_plan` держит соответствие нормативному плану); + идемпотентность — check→ensure/skip (AC-8 покрыт unit'ами resume/«противоречивое + состояние»); exit-контракт 0/2/1 (`test_exit_code_contract`); манифест manual-step честный: + инструкция → подтверждение → API-верификация, без TTY — немедленный exit 2. +- **FR-3** ✅ — webhook-секреты строго субпроцессом `gen_secrets.py` (структурный тест); + bundle-креды — stdlib `secrets` (token_hex ≥16 байт, unit проверяет длину); в репо только + пустые плейсхолдеры (`test_bundle_secrets_in_example_are_empty_placeholders`); права 600; + без перетирания без `--force-secrets` (`test_merge_missing_secrets_never_overwrites_without_force`). +- **FR-4** ✅ — BUNDLED_SETUP.md: все 14 разделов в порядке маршрута, fenced-команды + + «Проверка:»/PASS/FAIL в каждом исполняемом разделе, общие шаги ссылками на + LITE_SETUP §5–§8 / ONBOARDING / REPLICATION §4 (форк канона отсутствует), fail-closed имена + `Confirm Deploy`/`STOP` и «22 статуса» — сверкой импорта `plane_sync._PLANE_NAME_TO_KEY`. +- **FR-5** ✅ — три модуля без docker/сети/LLM; FORBIDDEN — импорт из + `test_no_host_hardcodes.py` (один источник истины); секрет-эвристика hex≥32/alnum≥40 с + негативным самочеком (не-evergreen); key-set-sync `${VAR}` ⊆ bundle-канона; заморозка + корневого compose зеркалом ассерта ORCH-102. +- **FR-6** ✅ — smoke = REPLICATION §4 поверх bundle (§11 дока, без форка), минимальный + сигнал «артефакты 01–04 в ветке» зафиксирован. +- **AC-матрица:** AC-4…AC-9 в файловой/структурной части — PASS (TC-01…TC-12 зелёные). + AC-1/AC-2/AC-3/AC-8(повторный прогон) в e2e-части — **ручная приёмка** на чистом хосте/VM + по рамке самих AC (в CI docker/LLM не гоняются) — остаётся за стадией приёмки, см. P2-2. + +### 2. Соответствие ADR (06-adr/ADR-001, adr-0038) + +- D1–D11 реализованы без отклонений; сквозной `adr-0038-bundled-replication-canon.md` заведён. +- **Прогрессивная автоматизация webhook (D7)** — единственное место, где реализация глубже + буквы ADR: `step_plane_webhook` регистрирует workspace-webhook прямой записью в Postgres + инсталляции. Сверено: это **не новый канон, а переиспользование** документированного + «пути Б» LITE_SETUP §5.4 (тот же INSERT-контракт, колонка-в-колонку), контракт чекпоинта + сохранён (верификация SELECT'ом; при отказе — fallback на честный manual-step с той же + проверкой), схема стабильна благодаря пину `v0.23.1`. D7 явно разрешает такую замену + manual-step → ensure «без правки ADR». Нарушения нет; в доке §7 чекпоинт 4 описан честно. +- **Трассировка (TRACEABILITY):** правка чужого маркированного блока одна — строка Type B в + `REPLICATION.md` §1 (артефакт ORCH-101); это запланированная точка расширения, прямо + предписанная ТЗ FR-6/§8 — инвариант ORCH-101 не сломан. Остальные изменения аддитивны + (новые файлы / новые секции CLAUDE.md, README архитектуры, CHANGELOG). +- Нормативы предшественников соблюдены: branch protection НЕ настраивается (D10 ORCH-009 / + INV-4 — явно в D6 и §14.6 дока), compose не форкается (adr-0037), «дефолт = боевое» не + нарушен (корневой `.env.example` не тронут). + +### 3. Качество кода + +- `pytest tests/ -q`: **1844 passed, 0 failed** (66s); новые тесты содержательные — unit'ы + чистых функций покрывают позитив/негатив/resume/противоречивое состояние, эвристики имеют + негативный самочек, ast-скан stdlib-allowlist реально закрыт. +- Бизнес-логика скрипта аккуратная: never-print секретов в stdout (только имена ключей), + маскированный лог при падении clone (токен в URL не утекает в вывод), `_psql` через stdin + (секрет не в argv), fail-fast preflight до любых мутаций, диагностика «кто не дождался + + хвост логов». Не багфикс-трек (feature) — требование регресс-теста-фиксатора BR-4/ORCH-019 + неприменимо. +- Замечания P2/P3 — ниже; ни одно не ломает инварианты конвейера и не относится к рантайму + платформы (скрипт исполняется только оператором на целевом хосте). + +### 4. Документация — обязательная проверка + +Выполнена явно, см. раздел «Документация» ниже. Обновлено всё требуемое в том же PR. + +## Findings + +### P0 — Blocker +- (нет) + +### P1 — Must fix +- (нет) + +### P2 — Should fix +- [ ] **P2-1. Секреты в argv субпроцессов** (`scripts/bootstrap_bundle.py`): + `step_init_gitea` передаёт `GITEA_ADMIN_PASSWORD` аргументом `--password` в + `docker compose exec gitea gitea admin user create …`, а `step_agent_git` — токен в + clone-URL аргументом `git clone http://oauth2:@…`. Значения видимы в `ps` хоста на + время исполнения. Формально AC-8 («секрет виден в stdout/логе») не нарушен, но это против + духа NFR-3 (ТЗ FR-2) и непоследовательно с собственной argv-гигиеной скрипта (`_psql` + прогоняет секреты через stdin с явным комментарием «секреты не попадают в argv, NFR-3»). + Рекомендация: для clone — использовать `git -c credential.helper`/`GIT_ASKPASS` либо + дописать компромисс в TR-7 (10-tech-risks) и шапку скрипта; для `gitea admin user create` + альтернатив CLI мало — минимум зафиксировать окно экспозиции в TR-7. Не блокер: разовая + операция оператора на одноарендном целевом хосте, угроза-модель совпадает с уже + зафиксированным компромиссом TR-7. +- [ ] **P2-2. Замер цифр «Требований к хосту» отложен на приёмку** (AC-4): BUNDLED_SETUP §2 + декларирует «подтверждаются замером приёмочного развёртывания» — на момент ревью цифры + (8 GB / 40 GB / 4 vCPU) синхронизированы с константами preflight структурным тестом, но + фактический замер ещё не зафиксирован. По рамке 03-acceptance-criteria (e2e — ручная + приёмка вне CI) это допустимо, однако при ручной приёмке AC-1/AC-2 результат замера нужно + зафиксировать (13-test-report / 15-staging-log или правка §2), иначе FAIL-условие AC-4 + «цифры с потолка» останется формально незакрытым. + +### P3 — Nice to have +- [ ] **P3-1.** `step_plane_webhook`: `slug`/`secret` интерполируются в SQL-строку без + экранирования одинарных кавычек. Секрет — hex от `gen_secrets` (безопасен), slug — + операторский ввод; кавычка в slug уронит INSERT. Риск минимален (ON_ERROR_STOP + + fail-safe fallback на manual-step), но дешёвое `value.replace("'", "''")` сняло бы класс + целиком. +- [ ] **P3-2.** `run_verify`: при одновременном health-FAIL и onboard `exit 2` функция + возвращает `EXIT_MANUAL` (2), маскируя ошибку (ожидался бы приоритет `1`). Поведенческая + мелочь read-only режима. + +## Документация + +| Артефакт | Статус | +|----------|--------| +| `CLAUDE.md` | ✅ новый раздел «Bundled-тираж (ORCH-103)» (паттерн ORCH-101/102) | +| `docs/architecture/README.md` | ✅ блок Type B — Bundled рядом с 10-common/Lite | +| `CHANGELOG.md` | ✅ запись `feat: ORCH-103` (детальная, D1–D11) | +| `docs/operations/REPLICATION.md` §1 | ✅ Type B → ✅ ORCH-103 + ссылка на BUNDLED_SETUP.md | +| `docs/deployment/BUNDLED_SETUP.md` | ✅ создан, 14 разделов канона D10, держится тестом | +| ADR | ✅ work-item `06-adr/ADR-001-…` + сквозной `adr-0038-bundled-replication-canon.md` | +| `07-infra-requirements.md`, `10-tech-risks.md` (TR-1…TR-9) | ✅ заведены архитектором, кросс-рефы из кода сходятся | +| `.gitignore` | ✅ `deploy/bundled/repos/` (NFR-3) | +| `README.md` «Известные ограничения» (ORCH-079) | ✅ проверено явно: PR не закрывает ни один из 3 открытых пунктов (Telegram 48h / intra-repo deps / пакетный автоном) — обновление витрины не требуется | + +`src/**` не изменён (PR — deploy/scripts/docs/tests), поэтому P0-правило «`src/` изменён без +документации» неприменимо; документация при этом обновлена полностью. + +## Итог + +`verdict: APPROVED` — P0/P1 отсутствуют; P2-1/P2-2 и P3 рекомендуется снять follow-up'ом или +при ручной приёмке Bundled-развёртывания (AC-1/AC-2/AC-3/AC-8 e2e-часть).