From cb32aa990797222f3e2dfbb87f11b862a2330fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Tue, 2 Jun 2026 09:32:39 +0300 Subject: [PATCH] =?UTF-8?q?feat(gate):=20re-scope=20router-gate=20?= =?UTF-8?q?=E2=80=94=20allow=20local=20dev,=20keep=20prod+discipline=20blo?= =?UTF-8?q?cks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit composer/npm moved from hard-blacklist to whitelist; git dev-allow (commit/add/branch/switch/checkout/stash/worktree) + push main-guard in shared shell-content-rules; read-only GitHub (get_*/actions_get/actions_list) in mcp-classifier. Prod-safety (deploy/prod-DB/secrets/workflow-triggers/MCP-write), discipline hooks, and main push/merge stay blocked. Spec+plan in docs/superpowers. tools regression 1991 GREEN. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...2026-06-02-router-gate-dev-prod-rescope.md | 290 ++++++++++++++++++ ...-02-router-gate-dev-prod-rescope-design.md | 131 ++++++++ tools/enforce-powershell-gate.test.mjs | 4 +- tools/enforce-router-gate.mjs | 8 +- tools/enforce-router-gate.test.mjs | 45 ++- tools/mcp-tool-classifier.mjs | 3 + tools/mcp-tool-classifier.test.mjs | 34 ++ tools/shell-content-rules.mjs | 20 +- tools/shell-content-rules.test.mjs | 69 +++-- 9 files changed, 557 insertions(+), 47 deletions(-) create mode 100644 docs/superpowers/plans/2026-06-02-router-gate-dev-prod-rescope.md create mode 100644 docs/superpowers/specs/2026-06-02-router-gate-dev-prod-rescope-design.md diff --git a/docs/superpowers/plans/2026-06-02-router-gate-dev-prod-rescope.md b/docs/superpowers/plans/2026-06-02-router-gate-dev-prod-rescope.md new file mode 100644 index 00000000..8d624b99 --- /dev/null +++ b/docs/superpowers/plans/2026-06-02-router-gate-dev-prod-rescope.md @@ -0,0 +1,290 @@ +# Router-gate dev/prod re-scope — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Разрешить локальную разработку (composer/npm/git/worktree) через контроллера, сохранив блок боевого/опасного и дисциплины. + +**Architecture:** Точечно расширить whitelist Bash-гейта (`enforce-router-gate.mjs`) дев-инструментами + разрешить dev-safe git в общем `shell-content-rules.mjs` (`classifyGitCommand`) с «стражем main» для push. Философия default-deny сохраняется; hard-blacklist опасного и дисциплинарные хуки не трогаются. + +**Tech Stack:** Node ESM, vitest (`vitest.config.tools.mjs`, root `app`). + +**Spec:** `docs/superpowers/specs/2026-06-02-router-gate-dev-prod-rescope-design.md` + +**Verify-команда (вся регрессия tools):** +`npx vitest run --root app --config vitest.config.tools.mjs` +Узкий прогон файла: добавить хвост `<имя>.test` (например `enforce-router-gate.test`). + +**Bootstrap-нюанс (важно):** до того как Task 3 (git dev-allow) применится, `git commit` ещё +заблокирован самим гейтом. Поэтому коммиты НЕ делаем по ходу — все правки складываем в рабочее +дерево, гоняем тесты, и **один раз** коммитим в конце (Task 5), когда git уже разрешён. Реализация — +в основной копии (worktree пока недоступен; это и есть bootstrap-исключение из спеки). + +--- + +## Задачи + +### Task 1: Разрешить `composer` (install/update/require/remove/dump-autoload) + +**Files:** + +- Modify: `tools/enforce-router-gate.mjs` (BASH_HARD_BLACKLIST ~line 59; SAFE_EXACT ~line 124) +- Test: `tools/enforce-router-gate.test.mjs` + +- [ ] **Step 1: Write failing tests** — добавить в конец `enforce-router-gate.test.mjs`: + +```js +import { matchBashHardBlacklist as mhb2, classifyBashCommand as cbc2 } from './enforce-router-gate.mjs'; + +describe('composer dev-allow (owner-authorized 2026-06-02)', () => { + it('allows composer install', () => { + expect(mhb2('composer install')).toBe(null); + expect(cbc2('composer install', {}).result).toBe('allow'); + }); + it('allows composer require / update / dump-autoload', () => { + expect(cbc2('composer require monolog/monolog', {}).result).toBe('allow'); + expect(cbc2('composer update', {}).result).toBe('allow'); + expect(cbc2('composer dump-autoload', {}).result).toBe('allow'); + }); + it('still allows composer install with -d working-dir', () => { + expect(cbc2('composer install -d app --no-interaction', {}).result).toBe('allow'); + }); +}); +``` + +- [ ] **Step 2: Run to verify FAIL** + +Run: `npx vitest run --root app --config vitest.config.tools.mjs enforce-router-gate.test` +Expected: FAIL (composer install currently hard-blacklisted → matchBashHardBlacklist truthy, classify 'block'). + +- [ ] **Step 3: Remove composer from hard-blacklist** — в `tools/enforce-router-gate.mjs` удалить строку: + +```js + { re: /\bcomposer\s+(?:install|update|require|remove)\b/, reason: 'composer install/update/require/remove запрещён' }, +``` + +- [ ] **Step 4: Add composer to whitelist** — в массив `SAFE_EXACT`, рядом с существующей `/^composer\s+(?:show|outdated)\b/`, добавить: + +```js + /^composer\s+(?:install|update|require|remove|dump-autoload|dump)\b/, // dev-allow 2026-06-02 +``` + +- [ ] **Step 5: Run to verify PASS** + +Run: `npx vitest run --root app --config vitest.config.tools.mjs enforce-router-gate.test` +Expected: PASS (включая новый describe). + +--- + +### Task 2: Разрешить `npm` (install/ci/run-скрипты) + +**Files:** + +- Modify: `tools/enforce-router-gate.mjs` (BASH_HARD_BLACKLIST ~line 60; SAFE_EXACT ~line 122) +- Test: `tools/enforce-router-gate.test.mjs` + +- [ ] **Step 1: Write failing tests** — добавить describe: + +```js +describe('npm dev-allow (owner-authorized 2026-06-02)', () => { + it('allows npm install / i / ci', () => { + expect(mhb2('npm install')).toBe(null); + expect(cbc2('npm install', {}).result).toBe('allow'); + expect(cbc2('npm ci', {}).result).toBe('allow'); + }); + it('allows npm run