**Не включены сознательно:** `cat`, `head`, `tail`, `type`, `more`, `less`. Они читают файлы в обход `validatePath`, включая `.env` и ключи. Поэтому идут в confirm.
Удаление и перемещение:
**Любой policy-флаг отменяет allow.** Даже safe-команда с `|`, `&&`, `;`, `$`, абсолютным путём или `..` уходит в confirm.
При вызове в панели появляется попап **Allow / Deny**. Модель ждёт:
net use, net user, net localgroup, net share, net stop, net start, net session, net file, net time, net accounts
Метасимволы в командах:
- **Allow** — команда выполняется, результат возвращается.
вертикальная черта, амперсанд, угловые скобки, точка с запятой, обратный апостроф, знак доллара, переносы строк
- **Deny** — возвращается `E_USER_DENIED`, команда не выполняется, очередь идёт дальше.
- **Ничего не нажать** — очередь стоит. Сброс: Stop, затем Start.
### Что требует подтверждения в панели
Если панель недоступна, confirm закрывается в отказ: `E_CONFIRM_UNAVAILABLE`. Это fail-closed: без явного «да» команда не выполняется.
### Что блокируется жёстко
Только два случая: пустая команда и команда длиннее 2000 символов. Всё остальное, включая `rm`, `curl`, `powershell`, `git push`, выполнимо через подтверждение.
### Pre-flight политика (главный слой)
Команда не в whitelist, но и не в blacklist. Например: `node script.mjs`, `python main.py`, `go build`, `cargo test`.
Модель обязана объявлять до отправки. Это записано в протоколе памяти (`protocol_policy`). Перед `dsh_bash` с policy-флагом модель пишет в тексте:
При такой команде в панели появляется попап с двумя кнопками Allow и Deny. Модель ждёт. Нажмите Allow — команда выполнится. Deny — вернётся ошибка E_USER_DENIED.
```
Policy: destructive, shell
Собираюсь выполнить (нужно ваше да):
1. rm -rf V:/Site/tmp/build
Не отправляю вызовы, жду подтверждения.
```
и останавливается. Пользователь отвечает «да» или «нет» в чате. Это настоящий контроль: команды видны целиком до выполнения. Панельный confirm — страховка, если модель забыла объявить.
### Чем это отличается от прежней блокировки
Раньше метасимволы и blacklist-паттерны блокировали команду намертво. Это создавало видимость защиты: обход через `node script.mjs` или `node -e` был тривиален и не логировался. Сейчас программа не блокирует, а спрашивает; каждое срабатывание флага пишется в консоль моста; граница — клик Allow/Deny и pre-flight объявление модели.
Ограничение, которое надо понимать: модель не детерминирована, она может забыть объявить. Тогда сработает панельный confirm, и вы увидите факт нарушения протокола. Если она забыла объявить, а вы нажали Allow не глядя, команда выполнится. Это осознанный выбор в пользу «человек решает», а не «программа запрещает».
- файлы с именем credential или secrets в имени (.json, .yaml, .txt)
- файлы с `credential` или `secrets` в имени (`.json`, `.yaml`, `.txt`)
Запись в .env, package.json, package-lock.json, pnpm-lock.yaml, yarn.lock требует подтверждения в панели.
Запись в `.env`, `package.json`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` требует подтверждения в панели.
### Защита путей
### Защита путей
Все пути относительные от папки из allowedRoots. Абсолютные пути запрещены. Попытка выйти за пределы через `..` или символическую ссылку даёт E_PATH_ESCAPE.
Для `dsh_read`, `dsh_write`, `dsh_edit`, `dsh_search`, `dsh_tree`: все пути относительные от `allowedRoots`, абсолютные запрещены, выход через `..` или символическую ссылку даёт `E_PATH_ESCAPE`.
---
Важно: это не распространяется на `dsh_bash` и запускаемые скрипты (`node`, `python`). Команда в shell работает под правами пользователя и может читать и писать за пределами workspace. Единственная защита здесь — policy-флаги (`absolute-path`, `parent-path`) плюс подтверждение. Именно поэтому `cat`, `type`, `head`, `tail` убраны из safe-list.