1. Песочница нужна даже при настроенных permissions
Когда люди впервые слышат про sandboxing, легко подумать: «Но мы же уже настроили permissions, deny-правила и protected paths, зачем ещё слой?» На самом деле это другой слой. Permissions отвечают на вопрос, что можно делать. Песочница — где это можно делать без катастрофы.
Самое полезное определение здесь очень земное: песочница — среда, где ошибка стоит дёшево. Не бесплатно, не незаметно — дёшево. Сломал Claude сборку в отдельной копии — вы раздражены, но живы. Сломал в main перед релизом — команда становится философской. Сломал на production — философию сменяет разбор инцидента.
Нагляднее всего разницу видно в маленькой таблице:
| Вопрос | Permissions | Песочница |
|---|---|---|
| На что отвечают | Какие действия разрешены | Где выполняются действия |
| Что уменьшают | Вероятность опасного шага | Цену ошибки |
| Типичный пример | deny для .env* и payments/** | test DB вместо production DB |
| Чего не заменяют | Git, тесты, review | permissions, review, здравый смысл |
Представьте, что вы учите человека водить машину. Permissions — это правило «нельзя ехать на красный». Песочница — автодром, а не оживлённое Садовое кольцо. Нужны оба разом. Дать Claude экспериментировать прямо на production — это квест в жанре «угадай, кто сегодня не спит».
Главное правило этой лекции простое: Claude должен экспериментировать там, где откат возможен быстро, дёшево и без настоящих данных.
Поэтому грамотный workflow не только запрещает лишнее, но и заранее выбирает среду, где даже разрешённое действие не нанесёт дорогой ущерб.
2. Ветка и worktree — два доступных уровня изоляции
Хорошая новость: первая песочница уже под рукой — это Git. И он даёт не одну степень свободы, а сразу две: обычную ветку и отдельную рабочую копию через worktree. Издалека они выглядят почти одинаково, но в реальной работе разница у них земная.
Ветка — это минимальный уровень изоляции. Она хорошо годится для review-required задач: меняете код, гоняете тесты, читаете diff и не трогаете среду вокруг проекта. Поправить сортировку refund-запросов в support inbox, подчистить код в support/ без правок инфраструктуры — ветки хватает: не мешаете main, коммитите мелко, откатываетесь в любой момент.
Worktree — это уже следующая ступень: вторая директория с тем же репозиторием, но в отдельной ветке. Если ветка — новая линия истории, то worktree — ещё и вторая рабочая комната: в одной обычная работа, в другой — эксперимент, который не пачкает текущую папку, не конфликтует с открытыми в IDE файлами и не гоняет вас туда-сюда.
git switch main
git pull
git worktree add ../commerce-os-boot-upgrade -b chore/boot-upgrade
cd ../commerce-os-boot-upgrade
claude # Claude работает в отдельной директории и не трогает основную копию
Такой подход особенно хорош, когда задача уже пахнет «осторожно, это может поломать сборку»: обновить библиотеку отчётов, перестроить Gradle-конфиг, проверить альтернативную реализацию. Главное удобство worktree даже не в Git как таковом — в психологическом комфорте: вы видите, что эксперимент живёт отдельно, и соблазн сделать опасное «быстренько здесь же» резко падает.
Но у worktree есть честное ограничение: он изолирует файлы и Git-состояние — и не изолирует ОС, переменные окружения, занятые порты, локальную базу. Меняете код — отлично. Меняете ещё и среду — worktree уже мал.
3. Одной ветки мало — контейнер и VM
Иногда проблема не в коде, а в среде, где этот код живёт. Откройте хоть десять worktree — но если все они смотрят в одну локальную базу, используют один .env и один установленный JDK, настоящей изоляции не получится. В таких случаях на сцену выходят контейнеры и виртуальные машины.
Контейнер разработки — это удобный способ отделить зависимости и окружение от основной машины. Он особенно полезен при обновлении рантайма, сборочного инструмента, системных библиотек, локальных сервисов, сложного набора зависимостей. Хороший пример — risky dependency upgrade в Commerce OS, задевающий backend, PostgreSQL и тестовый профиль приложения: после такого эксперимента основная локальная версия проекта должна запускаться как ни в чём не бывало.
services:
db-test:
image: postgres:18.3
environment:
POSTGRES_DB: commerce_test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
tmpfs: /var/lib/postgresql/data # данные исчезнут после остановки
Контейнер здесь даёт особенно важную вещь — эфемерность. Остановили — среда исчезла. Никаких долгоживущих «ой, у меня в локальной базе осталось что-то странное ещё с прошлого четверга». Для risky operations эффект почти терапевтический.
Виртуальная машина нужна реже, но она полезна там, где контейнера уже мало: проверить команды у системного уровня, включить агрессивный permission mode на одноразовый эксперимент, повозиться с непроверенными утилитами. Контейнер изолирует среду неплохо, VM даёт границу жёстче: отдельную ОС, отдельную ФС, отдельную сетевую картину мира. Тяжелее и медленнее — да. Ради правки README — смешно. Ради рискованного сценария — правильная цена за спокойствие.
И здесь важно не впасть в другую крайность. Dev container и VM не нужны ради каждого опечатанного метода: песочница должна быть соразмерна риску — иначе разработка превращается в бюрократический спорт.
4. Данные тоже должны жить в песочнице
Очень частая ошибка звучит так: «Код вынесу в worktree, а данные оставлю настоящие, чтобы всё было реалистично». Вот здесь и прячется одна из самых коварных ловушек: песочница без изоляции данных — половина песочницы. А иногда её имитация.
Если рискованная операция касается базы, очередей, платежей, массовых обновлений, импортов или скриптов очистки — нужна не просто отдельная папка с кодом, а отдельные данные, синтетические или тщательно санитизированные. Production dump с одной замазанной колонкой — всё ещё слишком близко к настоящим клиентам, заказам и проблемам.
{
"orderId": "test-order-1001",
"customerEmail": "demo@example.com",
"refundAmount": 49.99,
"currency": "USD",
"reason": "duplicate-order"
}
Такой пример выглядит скучно, но в этом и его прелесть: он похож на реальность настолько, чтобы воспроизвести сценарий, и при этом без реальных customer данных. Именно это и есть здравая инженерия, а не «давайте просто возьмём дамп продакшена, мы же аккуратно».
То же самое касается конфигурации. Если хватает .env.example — не тащите настоящий .env. Если заводится application-test.yml — не запускайте эксперимент на боевом профиле. Если нужен доступ к БД — пусть это будет test DB с фейковыми учётными данными, а не production-credential, который «я потом удалю». История разработки знает много страшных слов, и одно из самых страшных — «потом».
Полезно держать в голове простую формулу: код, среда и данные образуют одну систему. Изолировали только код, оставили настоящие данные — sandboxing уже треснул. Изолировали только данные, но запускаете из основной копии на permissive mode — трещина на месте. Настоящая песочница начинается там, где согласованы все три.
5. Выбор песочницы по уровню риска
Когда терминов становится много, очень хочется волшебную кнопку «подскажи, что брать». И такая кнопка в реальной команде обычно оборачивается маленькой матрицей выбора. Держите её прямо в Workflow Kit, рядом с RISK_CLASSIFICATION.md, — чтобы решение принималось по привычке, а не по вдохновению.
Ниже — компактная версия такой матрицы для Commerce OS:
| Ситуация | Минимально разумная песочница | Почему |
|---|---|---|
| README, docs, маленький локальный refactor | отдельная ветка | Изолируем diff, больше ничего не нужно |
| Многофайловая правка в support/ | ветка или worktree | Нужна чистая история и безопасный откат |
| Dependency upgrade, build-эксперимент | worktree + контейнер | Изолируем и файлы, и окружение |
| Schema/data change | worktree + test DB + synthetic data | Нельзя трогать реальные данные |
| Write-capable MCP | контейнер или VM + test env | Ошибка не должна выйти в production |
| Массовый delete/refactor script | throwaway repo/worktree + sample data | Нужно сначала «проиграть» сценарий |
А вот как выбор фиксируется в артефакте:
## Обновление зависимостей
Риск: review-required
Песочница: worktree + dev container
Данные: только test DB
Разрешено: edit, build, tests
Запрещено: production secrets и push в main
Заметьте, как красиво здесь сходятся предыдущие лекции и сегодняшняя. Риск уже классифицирован. Capability envelope уже понятен. Теперь к нему просто добавляется конкретная среда исполнения — и решение выходит взрослым: не «посмотрим по ходу», а «вот где именно разрешено экспериментировать».
На практике это сильно упрощает жизнь команде. Вместо спора «можно я быстро прогоню это локально?» появляется нормальный инженерный ответ: «Да, но только в worktree, на test DB и без реальных ключей». Звучит не так романтично — зато намного лучше переживает понедельник утром.
6. Commerce OS: массовые операции без героизма
Лучше всего идея песочницы закрепляется на конкретном сценарии. Представьте Commerce OS: массовое исправление статусов refund-запросов после сбоя в старом процессе импорта. Безобидной задача не выглядит — касается данных, может задеть финансы, испортить историю заказов. «Просто открою Claude в основной папке и посмотрим» — плохой план.
Сначала команда классифицирует задачу как review-required с близостью к high-risk. Уже на этом шаге становится ясно: никаких real credentials, никаких действий против production DB, никакого permissive mode в основной копии. Дальше — отдельный worktree, а рядом test DB в контейнере, в неё грузится синтетический набор refund-сценариев: частичный возврат, дубликат, отмена, ручная проверка.
Дальше workflow примерно такой:
flowchart TD A[Классифицировали риск] --> B[Создали worktree] B --> C[Подняли test DB] C --> D[Claude работает только в песочнице] D --> E[Проверили diff и тесты] E --> F[Человек принимает решение]
В этот момент Claude уже очень полезен: найдёт затронутые классы, предложит безопасный SQL или Java-сценарий, поможет с regression-тестами, проверит, не выходит ли diff за рамки refunds/ и support/. Но всё это внутри среды, где ошибка дешёвая. Скрипт пометил лишние записи — откатываете test DB. Сломал build — worktree удаляется, основная копия чиста. Возникло сомнение в логике — пересматриваете план, не трогая ничего настоящего.
Самый важный момент здесь психологический. Песочница не делает безопасной задачу. Она делает безопасным эксперимент. А это уже огромная разница: зрелая команда не бросается «чинить прод» — она сначала репетирует действие там, где ошибка стоит только времени и лёгкого сарказма коллег.
7. Dry-run, backup и staging не заменяют песочницу
Здесь начинаются тонкие, но очень важные различия. Многие разработчики, услышав слово «sandbox», отвечают: «У нас есть dry-run» или «Мы делаем backup перед запуском». Механизмы полезные — но не тождественны песочнице: они про другое.
| Механизм | Что даёт | Чего не даёт |
|---|---|---|
| Dry-run | Показывает предполагаемое действие | Не проверяет реальные побочные эффекты среды |
| Backup | Даёт шанс откатиться после беды | Не делает ошибку дешёвой и быстрой |
| Staging | Даёт похожую среду | Не всегда изолирована и часто общая для команды |
Dry-run — это хорошая репетиция без выполнения. Но что произойдёт при настоящем изменении состояния, он не проверяет: скрипт красиво печатает план обновления, а на реальном запуске падает из-за локов, прав, неожиданной схемы или несоответствия версии библиотеки. Backup — это вообще не про профилактику, а про спасение после аварии: жить только за счёт backup — как ездить без тормозов, зато с хорошей страховкой.
Со staging история ещё интереснее. Он полезен, но часто общий для команды, там идут параллельные проверки, и для опасного «я просто попробую» подходит не всегда. Staging хорош как приближение к реальности после локальной песочницы, а не вместо неё: сначала локальный sandbox, потом staging, — не наоборот.
Именно поэтому «мы же сделали backup» — не оправдание отсутствия песочницы. Backup — ремень безопасности после ошибки. Песочница — автодром до ошибки. Разница, как видите, весьма ощутимая.
8. Песочница не заменяет дисциплину
Есть соблазн увидеть в sandboxing волшебную таблетку: мол, есть worktree, test DB и контейнер — можно расслабиться, «Claude сам разберётся». К сожалению, инженерия так не работает. Песочница не заменяет маленькие diff, чтение изменений глазами, тесты — и уж точно не отменяет человеческое решение там, где ставка высока.
Ловушки те же, что уже разбирали: настоящий .env в worktree, почти production dump в test DB. Формально песочница есть, фактически нет. Ещё одна классика — включить permissive mode и решить, что раз всё в отдельной папке, можно не следить, какие команды Claude запускает. Но отдельная папка не изолирует shell-эффекты на вашей машине, не защищает системные каталоги и не гарантирует, что кто-то не смотрит в неправильную базу.
Есть и более будничные промахи. Например, worktree сделали — а через неделю не понимаете, откуда «ещё одна почти такая же ветка», удалить забыли. Или контейнер подняли на тестовом профиле, а приложение подключилось к старой локальной БД, потому что переменная окружения осталась прежней. Именно в такие моменты и видно: sandboxing — не роскошь и не красивый термин из политики команды. Это привычка проверять, чем вы на самом деле управляете: только папкой, папкой и средой, или папкой, средой и данными разом.
Когда этот навык закрепляется, песочница перестаёт ощущаться бюрократией. Она становится спокойным инженерным рефлексом: сначала сделать ошибку дешёвой, а уже потом нажимать Enter.
Но сделать ошибку дешёвой — ещё не то же, что разрешить change идти дальше. Sandbox страхует эксперимент, а право на путь в prod-sensitive зону оформляется отдельно: через deployment boundary и человеческое go/no-go решение.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ