fix(config): allow Read tool to open .env.example and .env.template #39
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/config/allow-env-example-read"
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?
Что сделано
.opencode/opencode.jsonpermission.read: после"**/.env*": "deny"добавлены"**/.env.example": "allow"и"**/.env.template": "allow"(findLast — allow побеждает для точных имён placeholder-файлов).tests/test_permissions.py: добавлены 2 теста —test_read_block_env_allow_rules(4 ассерта структуры read-блока:**/.env*=deny,**/.env.example=allow,**/.env.template=allow,**/id_ed25519.pub=allow — без регрессии прецедента) иtest_env_example_has_no_real_secrets(regex safety net: 8 паттернов реальных секретов — OpenAI/GitHub/Slack/AWS/Google/JWT/long-hex — fail если найден)..opencode/skills/configure-opencode/SKILL.md: исправлено описаниеread(документировало «массив glob-паттернов», но по схеме и факту — объектpattern → actionс findLast).3 логических коммита: config / test / docfix.
Почему
.env.example— placeholder-шаблон без реальных секретов, уже закоммичен в git и виден на Forgejo remote. Но**/.env*(deny) ловил.env.exampleчерез glob, и более позднего allow не было → Read tool не мог открыть безопасный файл. Прецедент**/id_ed25519.pub: allow(allow после deny через findLast) уже работает в конфиге — та же логика применяется для placeholder env-файлов..env.templateзарезервирован в.gitignore:36— future-proofing той же сущности. Документация расходилась с реальным конфигом (массив vs объект).Watch out
**/.env*(deny) ДОЛЖЕН стоять ДО**/.env.example/**/.env.template(allow) — порядок в JSON сохранён (объекты сохраняют insertion order вjson.load). Если переставить — deny снова победит..env(реальные секреты) остаётся denied — 4 правила (*.env,.env,**/.env,**/.env*) не тронуты..env.example/.env.templateне подпадают под первые три (те требуют, чтобы путь заканчивался на.env)..env.production/.env.local/.env.stagingостаются под**/.env*deny — для них явного allow нет.check-permissions.pyинспектирует толькоbashallow-правила, НЕ read-блок → CI не ломается.Pending
—
Closes #38
Closes #38
Code Review Summary
Точечный fix issue #38: 3 правки (config / test / docfix), 46 additions / 1 deletion. Логика findLast корректна,
.env(секреты) остаётся denied, safety net тест предотвращает будущую утечку реальных секретов в placeholder-файл. CI green, риски низкие.Positives
**/.env*(deny) стоит ДО**/.env.example/**/.env.template(allow), порядок в JSON сохранён (объекты сохраняют insertion order вjson.load). Прецедент**/id_ed25519.pub: allowпосле**/id_ed25519: deny(line 172-174) — аналогичный паттерн, соблюдён.*.env,.env,**/.env,**/.env*) не тронуты..envостаётся denied — security regression отсутствует.test_read_block_env_allow_rulesпокрывает 4 ассерта структуры read-блока: deny для**/.env*, allow для.env.example/.env.template, allow дляid_ed25519.pub(регрессия прецедента). Стиль совпадает с существующими тестами (_load_config(), Google-style docstring, section comment с unicode box drawing).test_env_example_has_no_real_secrets— отличный safety net: 8 regex паттернов (OpenAIsk-, GitHubghp_/gho_/ghs_/ghu_/ghr_черезgh[posur]_, GitHub fine-grainedgithub_pat_, Slackxox, AWSAKIA, GoogleAIza, JWTeyJ…eyJ, long hex). Превентит будущую утечку реальных ключей в tracked placeholder-файл.import reдобавлен в alphabetical order (послеjson, передsubprocess) — ruff sort корректен.readтеперь описан как объектpattern → action(какbash), с семантикой findLast. Прежняя формулировка («массив glob-паттернов») расходилась с реальным конфигом.!.env.exampleи!.env.templateуже зарезервированы →.env.template(future-proofing) не создаст untracked file.permission.bash(line 134:config.get("permission", {}).get("bash", {})), НЕread-блок → CI не ломается. PR body это утверждает — подтверждено.fix(config): …conventional, body содержит 4 heading'а (## Что сделано/## Почему/## Watch out/## Pending) осмысленно, 3 логических коммита (config / test / docfix), только 3 целевых файла в diff.Cross-file impact
PR меняет writer (
opencode.jsonread-блок,SKILL.mdдокфикс). Readers:check-permissions.py— читает толькоpermission.bash, неread→ не сломается.configure-opencode— сам writer SKILL.md, не reader → не сломается.test_permissions.py— readeropencode.json(через_load_config()), но тесты обновлены в этом же PR (paired update) → окно сломанного main закрыто.Missing paired update отсутствует.
Suggestions (info, not blocking)
(?<![A-Za-z0-9])[a-f0-9]{40,}(?![A-Za-z0-9])(long hex token) может дать false positive на git SHA-1 (40 hex chars), если кто-то добавит комментарий с SHA в.env.example. Текущий файл чист, но паттерн широковат для будущего. Не blocking — при false positive тест просто укажет на конкретный match, и автор решит (whitelist SHA или сузить паттерн).Verdict: APPROVE