# Phase 7: SSH deployment Phase 7 завершена для подтверждённой NeoForge 1.21.1 / 21.1.252 комбинации. Добавлены `mcpack deploy`, SSH worker и host deployment state. Подробный контракт и подготовка/recovery — [deploy.md](deploy.md). ## Реальный host пользователя 2026-10-03 выполнен deployment на `crab@192.168.1.61:2228` (minipc): - Отдельный root: `/home/crab/workspace/minecraft-lab/minecraft-lab-neoforge-spike`. Базовый каталог для других сборок не используется как runtime. - Подтверждены Docker 27.4.1, Node 26.10.0 через nvm, rsync, GNU tar и zstd. Новые системные зависимости на remote host не устанавливались. - Создан host `.env` с ранее принятой EULA, UID/GID 1000:1000, memory 2G, port 25565, project minecraft-lab-neoforge-spike. Mode env=600, root=700. - SSH key host закреплён в локальном known_hosts. Password authentication использован для ControlMaster; пароль нигде не записан. Worker/rsync используют BatchMode и StrictHostKeyChecking=yes. - Clean release **0.0.4** построен в отдельном Git checkout, поскольку root development release 0.0.4 имеет dirty=true и намеренно не допускается deploy. Source repository пользователя не коммитился и immutable старый dist не менялся. - Release manifest SHA256: `4b9a060ecb74329c0c10ca8c24954f87f4b137dfb5240f844bb93208780a694f`. - Первый deploy создал runtime без backup (first deploy), загрузил pinned image/dependencies, запустил NeoForge и подтвердил status query + 10 s stability. - Повторный deploy завершился healthy noop. Deployment state complete, applied=false, noop=true; container StartedAt остаётся временем первого запуска `2026-10-03T15:40:01.458777215Z`. - Remote status query возвращает Minecraft 1.21.1. `online-mode=false` и `enforce-secure-profile=false`; world принадлежит 1000:1000, Backpacks/Core присутствуют, client-only Mouse Tweaks в server JAR нет. - Сервер оставлен запущенным. Game port остаётся на remote IPv4 loopback; инструкция SSH tunnel для клиента находится в deploy.md. - Локальный primary Phase 0 сервер на 25565 не останавливался и остался healthy. Свидетельства: `.tools/phase7-target-evidence/deploy-first.log`, `deploy-noop.log`, `verification.txt`, `primary-server-status.txt`. SSH config — `.tools/phase7-ssh-target/config`, только параметры соединения. ## Реальный изолированный SSH/rsync стенд `scripts/verify-phase7.sh` создал loopback SSH server на 22227 с временными ключами и новым Docker project minecraft-lab-phase7, port 25566. Полный source snapshot помещён в отдельный Git clone, dependencies скопированы как обычный ignored каталог (symlink node_modules делал worktree dirty). Проверены реальные операции: 1. Clean build `0.0.4`, первая передача rsync и запуск healthy. 2. Повторная передача команды deploy той же версии: ID и StartedAt контейнера совпали до/после, release не передавался повторно и restart не было. 3. Общий host lock заблокировал параллельный deploy до остановки сервера. 4. Clean build `0.0.5` с новым server override marker; update создал проверенный backup исходного runtime/release, запустил target и обновил active/previous. 5. World/level.dat и persistent mod-state вне world сохранились; новый marker применился после backup, unknown файлы не удалялись. 6. Ручное изменение managed config затем вызвало conflict/non-zero до stop/apply. Изменённый файл сохранён, state failed/applied=false. 7. Test container/network и временный SSH daemon остановлены; snapshots, оба releases/runtime/state/evidence сохранены. Стенд: `.tools/phase7-check.6dbBak`, свидетельства в его `evidence/`: `build-first.log`, `build-second.log`, `deploy-first.log`, `deploy-noop.log`, `noop-container.txt`, `locked.log`, `deploy-second.log`, `update-assertions.txt`, `manual-conflict.log`, `conflict-assertions.txt`, `primary-server-status.txt`. ## Автоматические проверки `npm test`: 57 tests pass. Deployment tests используют controlled Compose/Docker и проверяют first deploy, no-op, immutable version collision, backup-gated update/world/mod-state, manual conflicts/diff, точный перенос ручной правки в clean target, failure передачи/backup/startup, unresolved state, async lock во время upload, dirty provenance, unsafe SSH arguments и CLI option scope. При failure передачи source не останавливается. При failure backup target не запускается. Failed startup оставляет target binding, source pointers, verified snapshot и stopped state; старый pack не запускается автоматически. Это unit fault injection, а не имитация сбоев на пользовательском live host. Health failures с живым Docker проверены отдельно в Phase 6; tar failure и restore — в Phase 5. Обычный SSH update выше подтверждает интеграцию gate. ## Границы Первый реальный remote deploy и no-op проверены на host пользователя; обновление и ручной conflict — на loopback стенде. Forge остаётся непроверенным. Аккаунты отключены; LAN game port не открывался, используется tunnel. Новый unknown существующий мир не принимается автоматически. Failed/incomplete state блокирует следующий deploy до ручного recovery. Указатели каждый atomic, общая пара не transaction; state содержит этап committing и прежние значения. fsync, retention, off-host backup и автоматический recovery не реализованы. Remote agents автоматически не удаляются. Следующая Phase 8 — rollback с восстановлением snapshot и исходного release.