JavaRush /Курси /Claude code /Пісочниця для ризикованих операцій

Пісочниця для ризикованих операцій

Claude code
Рівень 23 , Лекція 3
Відкрита

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, справжньої ізоляції не вийде. У таких випадках на сцену виходять контейнери та віртуальні машини.

Контейнер розробки — це зручний спосіб відокремити залежності й оточення від основної машини. Він особливо корисний під час оновлення рантайму, інструмента збирання, системних бібліотек, локальних сервісів, складного набору залежностей. Гарний приклад — ризикове оновлення залежності в 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, невеликий локальний рефакторинг окрема гілка Ізолюємо diff, більше нічого не потрібно
Багатофайлова правка в support/ гілка або worktree Потрібна чиста історія й безпечний відкат
Оновлення залежності, експеримент зі збиранням worktree + контейнер Ізолюємо і файли, і оточення
Зміна схеми/даних worktree + test DB + synthetic data Не можна чіпати реальні дані
Write-capable MCP контейнер або VM + test env Помилка не повинна вийти в production
Масовий скрипт видалення/рефакторингу одноразовий репозиторій/worktree + зразкові дані Потрібно спочатку «програти» сценарій

А ось як вибір фіксується в артефакті:

## Оновлення залежностей
Ризик: review-required
Пісочниця: worktree + dev container
Дані: лише test DB
Дозволено: edit, build, tests
Заборонено: production secrets і push у main

Зверніть увагу, як красиво тут сходяться попередні лекції й сьогоднішня. Ризик уже класифіковано. Рамка можливостей уже зрозуміла. Тепер до неї просто додається конкретне середовище виконання — і рішення стає дорослим: не «подивимося по ходу», а «ось де саме дозволено експериментувати».

На практиці це дуже спрощує життя команді. Замість суперечки «можна я швидко прогоню це локально?» зʼявляється нормальна інженерна відповідь: «Так, але лише в 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 добрий як наближення до реальності після локальної пісочниці, а не замість неї: спочатку локальна пісочниця, потім 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 рішення.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ