JavaRush /Курсы /Claude code /L3 permissions и protected paths

L3 permissions и protected paths

Claude code
23 уровень , 1 лекция
Открыта

1. Одной личной настройки уже мало

Когда вы работаете в одиночку над маленьким экспериментом, легко решить, что достаточно выбрать аккуратный permission mode в своей сессии и жить спокойно. Но как только появляются команда, общий репозиторий и зоны, куда лучше не залетать без каски, личной настройки становится мало. Один осторожен, другой спешит, третий открыл не тот worktree. Claude у всех один, а последствия его действий для репозитория общие.

Давайте возьмём Commerce OS. Обычная review-required задача: поправить порядок refund-запросов в inbox поддержки. Читать support/**, гонять тесты, править код рядом с проблемой и не трогать payments/**, migrations/**, .env*. Но договорённость, живущая только в голове или в текущем prompt, хрупкая: сегодня Claude честно остался в поддержке, завтра решил «немного улучшить» соседний код в платежах. И вот уже не bugfix, а сюрприз в двух бизнес-критичных директориях.

В терминах уже знакомой модели здесь и виден предел capability envelope: он хорошо описывает рамку одной задачи, но сам по себе не делает её правилом репозитория. За это отвечают L3 permissions. L1 отвечает: что разрешено мне в этой сессии. L3что вообще допустимо для команды в репозитории. Командный baseline не зависит от настроения, дедлайна и количества кофеина в крови.

Здесь полезна простая аналогия. CLAUDE.md с фразой «не трогай payments/» — это табличка на двери. Хорошая, вежливая. Protected path и deny-rule — это замок. Если вся безопасность держится на табличке, то это не политика, а очень воспитанная надежда.

Вот такой фрагмент в CLAUDE.md полезен:

## Ограничения проекта
Не редактируй `payments/`, `migrations/` и `.env*` без явного одобрения.

Но сам текст ещё не мешает инструменту туда записать. Он фиксирует намерение; enforcement живёт в другом слое.

2. Три слоя permissions и место L3

Чтобы не запутаться в терминах, всю трёхслойную модель стоит один раз спокойно увидеть целиком. Иначе L1, L2 и L3 начинают смешиваться в один большой клубок, где уже неясно, кто что ограничивает и почему один и тот же запрет иногда срабатывает, а иногда нет. Слои не конкурируют — наслаиваются.

Слой На какой вопрос отвечает Кто владеет решением Пример
L1 — session permissions Что Claude может делать в моей текущей сессии? Разработчик read-only, plan-first, ask before edit
L2 — agent permissions Что может делать конкретный agent? Автор agent’а / workflow designer reviewer — только чтение, tester — тесты, без edit
L3 — team permissions Что вообще разрешено команде в этом репозитории? Команда / tech lead / managed policy deny для payments/**, migrations/**, .env*

Важный момент: L3 не отменяет L1 и L2 — накладывается сверху. Объявили payments/** protected path — зона закрыта, даже когда в сессии разрешены edits, а агент умеет писать в файлы. И наоборот: команда разрешила правки в support/** — reviewer-agent от этого не получил право редактировать, его L2-контракт может оставаться read-only.

Можно запомнить это так:

L1 задаёт рабочий режим разработчика.
L2 задаёт границы конкретного агента.
L3 задаёт правила площадки, на которой работают все.

На практике всё очень приземлённо: сессия разрешает правки в support/ после подтверждения, reviewer-agent read-only, а team policy отправляет попытки писать в payments/**, migrations/**, .env* и destructive-команды в deny или на согласование. Система от этого не запутывается — становится предсказуемее.

И ещё одна важная привычка курса: точные названия режимов, ключей и команд меняются от версии к версии, но сами слои инвариантны. Видите новый синтаксис — не паникуйте, а спросите: это L1, L2 или L3? И сразу понятно, куда его положить.

3. Allow, Ask и Deny — радиус действия, а не попапы

Очень легко воспринимать allow, ask и deny как раздражающие окна подтверждения. Но это плохой ракурс: тройка описывает не UX, а радиус действия ошибки. Вопрос не в том, сколько раз нажать Enter, а доползёт ли неудачное AI-действие до опасной зоны.

Самый удобный способ мыслить здесь — через такую таблицу:

Режим Что это означает по сути Где обычно уместен
allow действие безопасно настолько, что его можно выполнять без лишнего трения чтение файлов, поиск, запуск тестов, локальные диагностические команды
ask действие потенциально полезно, но должно пройти через человеческое решение edit, write, git push, изменения вне узкого approved scope
deny действие слишком рискованно для обычного потока работы protected paths, destructive команды, secrets, force push

Если совсем по-человечески, allow — это зона, где Claude может свободно работать, потому что даже ошибка там обычно дешева и быстро видна. Ask — рабочая зона с review-границей: здесь изменения нужны, но вы хотите видеть, куда именно идёт инструмент. Deny — это зона, где команда заранее решила: нет, сюда через обычный workflow не ходим.

Ниже — небольшой концептуальный пример. Точный синтаксис может отличаться в вашей версии, поэтому здесь важнее сама логика, чем каждое название ключа:

{
  "permissions": {
    "allow": ["Read", "Grep", "Bash(./gradlew test*)"], // чтение и проверки
    "ask": ["Edit", "Write", "Bash(git push:*)"],       // действия с review-границей
    "deny": ["Edit(./payments/**)", "Edit(./migrations/**)", "Edit(./.env*)"] // protected paths
  }
}

Заметьте: этот фрагмент не про «запретить всё», а про разумное деление. Утащите в ask каждое чтение и тест — команда возненавидит и инструмент, и того, кто так настроил. Перетащите в allow вообще всё — схема превратится в декоративную надпись на стене. Хорошее практическое правило такое: deny короткий, но жёсткий; ask покрывает то, что меняет состояние репозитория или процесса; allow — безопасное исследование, чтение и проверка.

Здесь удобно связать сегодняшнюю тему с прошлой лекцией про risk classification. Для low-risk режим мягче: много allow, немного ask, тот же короткий deny. Для review-required чтение и тесты в allow, edits и push в ask. Для high-risk Claude готовит план и артефакты, выполнение остаётся за человеком.

Уровень риска Типичный L3-подход
low-risk allow для чтения и безопасных правок в узкой зоне, ask для push, deny для protected paths
review-required allow для исследования и тестов, ask для любых edits, deny для чувствительных зон
high-risk AI в основном готовит материалы, а реальные действия остаются за человеком

Частая ошибка новичка звучит так: попап мешает — значит, срочно расширяем allow. Но повторяющийся ask не всегда плохая настройка. Иногда это честный сигнал, что вы зашли в review-required зону. Так и надо.

4. Protected paths — правило становится замком

Есть категории файлов и директорий, для которых общего «ну будьте аккуратны» недостаточно. Их надо выделять отдельно и защищать так, чтобы даже при неудачном стечении обстоятельств Claude не мог туда записать. Для этого и существуют protected paths — локальные зоны повышенной важности внутри репозитория.

В Commerce OS хорошие кандидаты видны почти сразу: payments/**, migrations/**, .env*, иногда infra/** или конфиги прав доступа. Опасны они не сложностью, а дорогим blast radius ошибки.

Путь Почему его защищают
payments/** платежная логика, деньги, возвраты, внешние провайдеры
migrations/** схема данных и потенциально необратимые изменения
.env* secrets и конфигурация окружения
infra/** окружение, деплой, доступы, общая инфраструктура

И вот здесь особенно важно помнить ключевую формулу лекции:

Prompt и CLAUDE.md задают намерение.
Permissions, rules, hooks и protected paths обеспечивают границы.

То есть protected path — уже не просто текстовое указание, а часть enforcement. Часто это связка deny-rule плюс hook, который срабатывает перед попыткой записи:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{ "type": "command", "command": ".claude/hooks/block-protected-paths.sh" }]
    }]
  }
}

Сам hook может быть маленьким и просто проверять, не попадает ли целевой путь в список защищённых. Не надо превращать его в космический корабль. Его задача — остановить запись до того, как она произошла. Рядом обычно живёт текстовое правило:

# rules/no-secrets-in-prompts.md
Никогда не вставляй API keys, tokens, passwords и production credentials
в prompts, task specs и примеры данных.

Зачем и правило, и hook? Rule помогает человеку и Claude правильно мыслить. Hook страхует, когда кто-то всё же попытался пройти, куда не следовало. Один слой обучает, другой страхует.

Переборщить легко. Объявите protected path половину репозитория — работать станет невозможно, команда начнёт искать обходы, стратегия потеряет доверие. Не «весь backend», а те области, где ошибка особенно дорога.

5. Managed settings и иерархия командной политики

Даже хорошая permission strategy мало помогает, если лежит не там, где её реально применяет команда. На ранних этапах это кажется скучной административной деталью, но именно отсюда растут истории формата «у меня всё работает не так, как у вас» — правила размазаны по разным уровням настроек.

Уровень Для чего подходит Чего туда лучше не класть
user личные удобства и персональные привычки командную security-политику
project общие правила репозитория личные временные эксперименты
local личные настройки для конкретного проекта обязательный baseline команды
managed организационные запреты и production-level policy всё, что должно свободно меняться каждым разработчиком

Если сказать проще, командная политика должна жить там, где она видна и работает для всех: обычно project, в более строгих окружениях — ещё и managed. Положили критичное правило только в user settings — командной стратегии у вас нет, есть личная дисциплина одного разработчика. Хорошо, но недостаточно.

Удобная структура в Workflow Kit может выглядеть так:

.claude/
  CLAUDE.md
  settings.json
  hooks/block-protected-paths.sh
  rules/no-secrets-in-prompts.md

Каждый файл несёт свою роль — контекст, разрешения, enforcement, правило поведения. Вместе — уже не хаотичный набор файлов, а система.

Отдельно важно сказать про local-уровень. Он полезен для заметок, персональных preferences, настроек под отладку. Но это плохое место для обязательной границы: правило про payments/** или .env*, живущее только в чьих-то local settings, защищает не проект, а его ноутбук.

А вот managed-уровень нужен там, где команда или организация хотят закрепить действительно неоспоримые вещи: не просто договорились, а зафиксировали сверху. Запрет на direct push в protected branches, запрет на автоматические destructive-команды в production-sensitive репозитории. Городить enterprise-машину сразу не нужно, но назначение слоя полезно понимать заранее.

6. Собираем рабочую L3-стратегию для Commerce OS

Теперь давайте сложим всё в одну рабочую картину, чтобы сегодняшняя лекция не осталась набором умных слов. Возьмём знакомый сценарий из Commerce OS: поправить порядок refund-запросов в inbox поддержки. На прошлой лекции мы присвоили бы задаче label review-required и собрали capability envelope. Сегодня идём дальше и превращаем этот label в командные границы.

Артефакт За что отвечает
RISK_CLASSIFICATION.md определяет risk label и capability envelope
settings.json проводит allow/ask/deny на уровне проекта
rules/no-secrets-in-prompts.md объясняет командное правило поведения
hooks/block-protected-paths.sh технически блокирует запись в опасные зоны
CLAUDE.md даёт контекст проекта, команды и соглашений, но не обеспечивает enforcement

Для нашей review-required задачи итоговый фрагмент может выглядеть так:

Risk level: review-required
Allowed: Read, Grep, tests, edits в `support/**`
Ask: write вне approved scope, `git push`
Forbidden: `payments/**`, `migrations/**`, `.env*`, force push
Rollback: revert PR, regression test остаётся в репозитории

А рядом — фрагмент settings.json:

{
  "permissions": {
    "allow": ["Read", "Grep", "Bash(./gradlew test*)", "Edit(./support/**)"], // рабочая зона задачи
    "ask": ["Write", "Bash(git push:*)"],                                      // review-граница
    "deny": ["Edit(./payments/**)", "Edit(./migrations/**)", "Edit(./.env*)"] // protected paths
  }
}

Что это даёт на практике? Во-первых, команда перестаёт спорить на каждом PR, можно ли доверять Claude, — доверие встроено в систему. Во-вторых, ревьюер видит не только diff, но и границы, в которых он появился. В-третьих, если кто-то работает смелее обычного, L3 permissions всё равно удерживают общий baseline проекта.

И это, пожалуй, главный полезный результат сегодняшней темы. С нормальной L3-стратегией permissions перестают быть разговором про раздражающие подтверждения и становятся разговором про предсказуемость. Вы открываете задачу, присваиваете уровень риска — и дальше Claude работает не «где получится», а в пределах хорошо освещённой мастерской, где опасные комнаты закрыты, инструменты разложены по местам, а на столе лежит план.

Отдельный сюжет — облачные поверхности Claude Code

Облачный планировщик и облачное ревью (условно /ultraplan, /ultrareview или их аналоги — точное имя и доступность могут меняться от версии к версии) исполняются вне вашей локальной session и подчиняются отдельной permission-модели: своими границами облачного аккаунта, отдельным учётом расходов, отдельным журналом аудита и собственным набором разрешённых путей.

Для команды это означает простую, но неудобную вещь: облачные агенты должны жить в той же логике «разрешить / спросить / запретить», что и локальные subagents. Безопасной по умолчанию она не считается. Чувствительные пути — секреты, данные клиентов, файлы, которые по соглашению не покидают on-prem — не должны утекать в облако сами собой, для них нужен явный список разрешений. А след аудита — что отправлено, что вернулось, кем запущено — обязан попадать в общее логирование команды, иначе проверка соответствия превращается в гадание.

Для задач уровня review-required это не замена локальным permissions, а ещё одна permission-поверхность поверх них. Решение об одобрении diff всё равно за человеком, кто бы ни делал review. Точные механизмы — opt-in/out, scoped tokens, конфигурация разрешённых путей — зависят от версии Claude Code. Модель короткая: облачная поверхность — ещё один инструмент со своим blast radius, и описывать её в team policy нужно явно. В терминах L3 это та же работа, что и для локальных deny-rules и hooks, просто на поверхности, которая исторически могла оставаться вне поля зрения команды.

1
Задача
Claude code, 23 уровень, 1 лекция
Недоступна
Ужесточение `.claude/settings.jsonc` для L3 baseline
Ужесточение `.claude/settings.jsonc` для L3 baseline
1
Задача
Claude code, 23 уровень, 1 лекция
Недоступна
Подключение hook для блокировки protected paths
Подключение hook для блокировки protected paths
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ