# Дизайн выполнения: автономный прогон миграции на Gitea в Yandex Cloud

## Цель

Описать контракт **самостоятельного выполнения** переноса git-хостинга на self-hosted Gitea в
Yandex Cloud — то есть как контроллер прогоняет миграцию сам, а владелец только вводит учётные
данные в обозначенных точках. Дизайн самого решения — `2026-06-15-gitea-yc-migration-design-3.md`;
пошаговая инструкция — `docs/ops/gitea/2026-06-15-gitea-yc-migration-runbook.md`. Эта спека —
контракт безопасного автоматического прогона: фазность, идемпотентность, точки ввода секретов,
откат.

Результат: виртуальная машина в Yandex Cloud с Gitea по HTTPS; все локальные ветки/теги залиты
(резервная копия); off-box зеркало настроено и проверено.

## Фазы выполнения {#E1}

Прогон делится на упорядоченные фазы; каждая последующая стартует только при успехе предыдущей:

- **Ф0. Верификация окружения (только чтение).** Проверить наличие и авторизацию инструментов
  управления (CLI облака), git, ssh; текущее состояние репозитория (ветки, теги, использование
  LFS). Без изменений состояния. Если инструмента/авторизации нет — выполнение останавливается на
  точке ввода учётных данных (E3), не гадая.
- **Ф1. Провижининг VM.** Создать виртуальную машину по параметрам дизайна (D6 design-3): размер,
  диск, ОС, та же сеть, что боевой; публичный статический адрес; открыть порты 80/443 (+2222 при
  необходимости).
- **Ф2. Развёртывание Gitea.** На VM установить контейнерную среду, доставить compose-конфиг
  комплекта, поднять Gitea + БД + авто-HTTPS.
- **Ф3. Инициализация Gitea.** Создать администратора, токен записи, пустой репозиторий.
- **Ф4. Заливка (бэкап).** Добавить remote, залить все ветки и теги (+ LFS при наличии); проверить
  совпадение числа веток/тегов/коммитов.
- **Ф5. Off-box зеркало.** Настроить push-mirror на сторонний хостинг и проверить фактическую
  синхронизацию.

## Идемпотентность и проверка перед необратимым {#E2}

- Каждая фаза перед мутацией **проверяет текущее состояние** и пропускает уже сделанное (создание
  VM пропускается, если ВМ с тем же именем существует; remote не дублируется; заливка повторно
  безопасна).
- Любое **необратимое или платное** действие (создание VM, запись на прод-уровне) выполняется
  только после успешной Ф0 и явной проверки, что объект ещё не создан.
- Сбой шага останавливает прогон на этом шаге; следующие фазы не запускаются.

## Ввод учётных данных и секреты {#E3}

- Учётные данные (токен авторизации облака, пароль БД, токен Gitea, токен зеркала) вводит
  **владелец** в обозначенных точках; контроллер их **не генерирует за владельца и не хранит**.
- Ни один секрет не попадает в репозиторий, в спеку, в план и в логи. В артефактах — только
  плейсхолдеры.
- Точка ввода токена авторизации облака — out-of-band (интерактивная инициализация CLI), не
  выражается как шаг плана; план продолжается после неё.

## Откат {#E4}

- Ф1: созданную VM можно удалить/остановить (расход обратим — см. D6 design-3).
- Ф2–Ф3: контейнеры сносятся `down`; данные — в томах (полное удаление — отдельным осознанным
  действием).
- Ф4: заливка только добавляет данные на новый remote; исходный локальный репозиторий не меняется
  (откат не требуется).
- Ф5: зеркало отключается в настройках репозитория Gitea.

## Допущение об окружении {#E5}

Команды плана выполнения **составлены без живой проверки окружения** (проверка окружения на момент
написания заблокирована). Поэтому:

- Ф0 (только чтение) обязательна **первой** — она верифицирует реальные версии/авторизацию/пути; её
  результат может потребовать **корректировки конкретных команд** последующих фаз на исполнении.
- Точные флаги CLI облака, имена образов и сетевые идентификаторы помечаются как ⚠️ «сверить на
  исполнении» и не выдаются за факт.

## Критерий готовности выполнения {#E6}

Прогон считается успешным, когда выполнены ВСЕ условия:

- Ф0 прошла: инструменты есть и авторизованы (или явно зафиксирована точка ввода E3);
- VM создана и доступна; Gitea открывается по HTTPS;
- число веток/тегов и счёт коммитов в `main` на Gitea совпадает с локальным (бэкап подтверждён,
  не «на словах»);
- push-mirror синхронизировался — репозиторий с ветками реально виден на стороне зеркала;
- секреты не утекли в репозиторий/план/логи.

```verified-context-json
[
  {"id":"E-host","kind":"EXTRACTED","ref":".github/workflows/deploy.yml","anchor":"LIDERRA_HOST: 111.88.246.137"},
  {"id":"E-push","kind":"EXTRACTED","ref":"docs/ops/gitea/2026-06-15-gitea-yc-migration-runbook.md","anchor":"git push gitea --all"}
]
```
