fix(config): allow Read tool to open .env.example and .env.template #38
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Контекст
Файл
.env.example— это placeholder-шаблон без реальных секретов. Он уже закоммичен в git и виден на Forgejo remote. Однако текущая конфигурацияpermission.readв.opencode/opencode.jsonЗАПРЕЩАЕТ чтение этого файла через Read tool — это баг (misconfiguration), поскольку безопасный placeholder-файл, уже находящийся в git, не должен блокироваться.Текущее состояние
.opencode/opencode.json(строки 161–173), блокpermission:Механизм (findLast)
opencode
readpermission использует glob-паттерны с findLast-семантикой — ПОСЛЕДНЕЕ совпадающее правило побеждает. Паттерн**/.env*(deny) на строке 169 совпадает с.env.example, и более позднегоallowдля него нет → DENY побеждает. Существующий**/id_ed25519.pub: allow(строка 172) демонстрирует тот же паттерн: поместиallow-правило ПОСЛЕ совпадающегоdeny, и findLast позволит ему выиграть для конкретного имени файла..env(реальные секреты)Сейчас запрещён 4 перекрывающимися правилами (
*.env,.env,**/.env,**/.env*). Корректно защищён — должен остаться запрещённым. Файла.envв репо не существует (gitignored в.gitignore:33)..env.templateИмя зарезервировано в
.gitignore:36(!.env.template), файл пока не существует. Future-proofing — та же логическая сущность, что.env.example(шаблон без секретов).CI/validator
check-permissions.pyинспектирует толькоbashallow-правила, НЕ блокread. Добавлениеreadallow НЕ сломает CI.Тесты
tests/test_permissions.pyНЕ имеет тестов для блокаread(только bash-правила). Нужен новый тест, фиксирующий структуру.Документационный баг в
.opencode/skills/configure-opencode/SKILL.md:115Описывает
readкак "массив glob-паттернов" (массив allow-паттернов), но согласно официальной схеме opencode И фактическому конфигу,read— это ОБЪЕКТ, отображающий glob → action (allow/deny/ask). Нужно однострочное исправление.Задача
Внести 3 правки в
/root/workspace/opencode-config/:Правка 1 —
.opencode/opencode.json, блокpermission.readПосле строки 169 (
"**/.env*": "deny",) вставить ДВЕ новые строки:Результат (строки 169–172):
findLast гарантирует, что
allowпобеждает только для ТОЧНЫХ имён файлов.env.exampleи.env.template..env(секреты) остаётся запрещённым — его 4 правила не трогаются, а.env.example/.env.templateне подпадают под*.env/.env/**/.env(те требуют, чтобы путь ЗАКАНЧИВАЛСЯ на.env).Правка 2 —
tests/test_permissions.pyДобавить новую тестовую функцию, проверяющую структуру блока
read:"**/.env*"== "deny" (сохранено — секреты защищены)"**/.env.example"== "allow" (новое)"**/.env.template"== "allow" (новое)"**/id_ed25519.pub"== "allow" (без регрессии)Также протестировать, что содержимое
.env.exampleостаётся placeholder-only (без реальных секретов) — прочитать файл в тесте, regex'ом проверить очевидные паттерны секретов, упасть, если найден реальный секрет. Это защитная сетка (safety net).Следовать существующему стилю тестов в
tests/test_permissions.py(посмотреть, как bash-тесты грузят config JSON и ассертят правила). Тест должен загрузить.opencode/opencode.json, перейти вpermission.readи assert ключи/значения выше.Правка 3 —
.opencode/skills/configure-opencode/SKILL.md:115Исправить описание:
read— это объектpattern → action(allow/deny/ask), НЕ массив allow-паттернов. Одна строка.Контракты
permission.readв.opencode/opencode.json— объект с findLast-семантикой: последнее совпадающее правило побеждает.json.load).**/.env*(deny) ДОЛЖЕН остаться в конфиге и остаться ДО**/.env.example/**/.env.template(allow), чтобы findLast позволил allow выиграть для конкретных имён.**/id_ed25519.pub: allow— существующий прецедент того же паттерна (allow после deny), не должен регрессировать.json.loadпо образцу существующих bash-тестов вtests/test_permissions.py.Инварианты
.env(реальные секреты) остаётся DENY (4 правила не трогаются:*.env,.env,**/.env,**/.env*)..env.example— placeholder, уже в git, уже виден на Forgejo remote..env.template— зарезервирован в.gitignore:36, файл пока не существует.check-permissions.pyне инспектирует блокread→ правки не ломают CI.bashallow/deny правилах.Граничные случаи
.env.production,.env.local,.env.staging— подпадают под**/.env*(deny), явного allow для них НЕТ → остаются DENY. Корректно (могут быть реальные секреты)..env.exampleв поддиректории (например,packages/foo/.env.example) —**/.env.exampleсовпадает через**→ allow побеждает. Корректно (placeholder в любом месте репо безопасен)..envв корне —*.env,.env,**/.envсовпадают, все deny, более позднего allow для.envнет → DENY. Корректно..ENV.example— не совпадает ни с одним allow (glob чувствителен к регистру на Linux) → остаётся под**/.env*deny. Корректно.Влияние на связанные компоненты
check-permissions.py— не затронут (инспектирует только bash-правила).tests/test_permissions.py— добавляется новая тестовая функция; существующие bash-тесты не затрагиваются..opencode/skills/configure-opencode/SKILL.md— однострочное исправление описанияread(объект, не массив)..env.exampleи.env.template; все остальные.env*файлы остаются под deny.check-permissions.py).Вне scope
bashcat .env.example— Read tool каноничен (AGENTS.md:78 "Use tools instead of bash"). Прецедент**/id_ed25519.pubНЕ трогал bash. НЕ добавлятьcat .env.example*allow в bash..env(реальные секреты) — остаётся denied, это корректно. Никаких изменений в 4 deny-правилах, его защищающих..env.template(пока только future-proofing в конфиге).Критерии приемки
.opencode/opencode.jsonпосле"**/.env*": "deny",стоят две новые строки:"**/.env.example": "allow",и"**/.env.template": "allow",(в указанном порядке)..env(*.env,.env,**/.env,**/.env*) сохранены без изменений.**/id_ed25519.pub: allowсохранён без изменений.tests/test_permissions.pyдобавлена тестовая функция, ассертящая 4 указанных ключа/значения блокаread..env.exampleне содержит реальных секретов (regex-проверка placeholder-содержимого).pytest tests/test_permissions.py).tests/test_permissions.pyне регрессируют..opencode/skills/configure-opencode/SKILL.md:115описаниеreadисправлено на "объект pattern → action (allow/deny/ask)".