# Правила репозитория — CVE-2026-111497

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

## Назначение

Репозиторий содержит переиспользуемый агент устранения для **CVE-2026-111497** — записи за
границы буфера (out-of-bounds write) в декодере Google Brotli. Ядро — набор детерминированных
bash-скриптов в `src/`; они возвращают компактный машиночитаемый вердикт и удерживают расход
токенов языковой модели на минимальном уровне.

## Границы ответственности

- `src/detect.sh` — **только чтение.** Не изменяет ни пакеты, ни службы, ни файлы конфигурации.
- `src/remediate.sh` — единственная точка изменения. Выполняет резервное копирование, проверку
  подлинности, сухой прогон, установку и перезапуск потребителей.
- `src/verify.sh` — **только чтение.** Подтверждает фактически достигнутый эффект.

## Обязательные инварианты

1. **Резервная копия до изменения.** `remediate.sh` всегда создаёт
   `/root/cve-2026-111497-fix-<timestamp>/` со старыми файлами `.so`, загружаемым `.deb`
   и снимком `dpkg` до установки чего-либо.
2. **Проверка подлинности.** Установка выполняется только после подтверждения, что changelog
   кандидата ссылается на `CVE-2026-111497`. В противном случае скрипт останавливается
   и эскалирует.
3. **Перезапуск потребителей.** Ни один процесс не должен сохранять отображённый уязвимый
   `libbrotlidec` после устранения. Это проверяется через `/proc/*/maps` и сравнение inode.
4. **Ноль секретов в репозитории.** Никаких ключей, паролей, токенов, реальных IP-адресов
   и имён хостов. Целевые хосты передаются как SSH-алиасы из `~/.ssh/config`.
5. **Формат файлов.** LF, без BOM, UTF-8. Файлы `.sh` коммитятся с режимом `100755`.
6. **`.ragraf/` не коммитится никогда** — правило находится в корневом `.gitignore`.

## Команды

```bash
# syntax check before delivery
bash -n src/common.sh src/detect.sh src/remediate.sh src/verify.sh

# field order is fixed: detect -> remediate -> verify
bash src/detect.sh ; echo "exit=$?"
bash src/remediate.sh
bash src/verify.sh
```

## Проверка

Изменение принимается только при одновременном выполнении всех перечисленных условий:

```bash
bash -n src/*.sh                       # no syntax error
shellcheck src/*.sh                    # no unresolved finding
ghagent doc --root .                   # markdown and privacy contract
```

Поведенческим доказательством служит полевой прогон на одноразовом хосте: `detect.sh`
возвращает `1`, затем `remediate.sh` возвращает `0`, затем `verify.sh` печатает
`VERIFY: PASS`.

## Порядок коммита (владелец, а не агент)

Снимите переопределяющие переменные и задайте идентичность владельца явно:

```bash
unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
git -c user.name='Mikhail Deynekin' -c user.email='Mikhail@Deynekin.com' commit -m '...'
git log -1 --format='%an <%ae> | %cn <%ce>'   # owner, never zwork
```

## Ловушки

| Ловушка | Симптом | Действие |
|---|---|---|
| `set -o pipefail` при `head`/`awk`, завершающихся досрочно | код 141 (SIGPIPE) при успешном выполнении | `pipefail` намеренно не включён в `common.sh` |
| Подключение файла состояния как shell | синтаксическая ошибка на `PRETTY_NAME` со скобками | читать значения через `state_get` |
| Inode, снятый по glob | записывается inode символьной ссылки, проверка устаревания ложно проходит | `find -type f -printf '%i'` |
| `printf '%s'` без перевода строки в цикле по юнитам | имена юнитов склеиваются, перезапуск молча ничего не делает | `printf '%s\n'` |
| `systemctl restart` юнита рабочего стола | потеря сеанса, обрыв VPN | юниты рабочего стола и инфраструктуры входят в `DESKTOP_INFRA_PAT` и помечаются как отложенные |
| Перезапуск демонов панели ISPmanager через `kill` | повреждение состояния панели | `mgrctl -m core --restart srvparam` |

## Запрещено

- Удалять файлы, которые задача не упоминает, без явного согласия владельца.
- Запускать `remediate.sh` без предшествующего `detect.sh` (состояние «до» обязательно).
- Форсировать установку пакета, когда проверка подлинности не пройдена.
- Включать автоматическое обновление или перезагрузку без присмотра на целевом хосте
  по собственной инициативе.
