# Repository rules — CVE-2026-111497

Scope: agents and humans working in this repository.
Priority: safety over speed. Every irreversible action is preceded by a backup and a sandbox
check of the same operation.

## Purpose

The repository holds a reusable remediation agent for **CVE-2026-111497**, an out-of-bounds
write in the Google Brotli decoder. The core is the set of deterministic bash scripts in `src/`;
they return a compact machine-readable verdict and keep the language model's token spend to a
minimum.

## Responsibility boundaries

- `src/detect.sh` — **read-only.** It changes no package, service or configuration file.
- `src/remediate.sh` — the only mutation point. It performs the backup, the authenticity gate,
  the dry run, the installation and the restart of consumers.
- `src/verify.sh` — **read-only.** It confirms the effect that was actually achieved.

## Mandatory invariants

1. **Backup before change.** `remediate.sh` always creates
   `/root/cve-2026-111497-fix-<timestamp>/` with the old `.so` files, the downloadable `.deb`
   and a `dpkg` snapshot before installing anything.
2. **Authenticity gate.** Installation happens only after the candidate changelog is confirmed
   to reference `CVE-2026-111497`. Otherwise the script stops and escalates.
3. **Restart the consumers.** No process may keep the vulnerable `libbrotlidec` mapped after
   remediation. This is checked through `/proc/*/maps` and inode comparison.
4. **Zero secrets in the repository.** No keys, passwords, tokens, real IP addresses or
   hostnames. Target hosts are passed as SSH aliases from `~/.ssh/config`.
5. **File format.** LF, no BOM, UTF-8. `.sh` files are committed with mode `100755`.
6. **`.ragraf/` is never committed** — the rule lives in the root `.gitignore`.

## Commands

```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
```

## Verification

A change is accepted only when all of the following hold:

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

The behavioural proof is a field run on a disposable host: `detect.sh` returns `1`, then
`remediate.sh` returns `0`, then `verify.sh` prints `VERIFY: PASS`.

## Commit order (owner, not agent)

Unset the overriding variables and set the owner identity explicitly:

```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
```

## Traps

| Trap | Symptom | Action |
|---|---|---|
| `set -o pipefail` with an early-exiting `head`/`awk` | exit 141 (SIGPIPE) on success | `pipefail` is deliberately omitted in `common.sh` |
| Sourcing a state file as shell | syntax error on `PRETTY_NAME` with parentheses | read values with `state_get` |
| Inode captured from a glob | the symlink inode is recorded, the stale check passes falsely | `find -type f -printf '%i'` |
| `printf '%s'` without a newline in a unit loop | unit names concatenate, restart silently does nothing | `printf '%s\n'` |
| `systemctl restart` of a desktop unit | lost session, dropped VPN | desktop and infrastructure units are in `DESKTOP_INFRA_PAT` and reported as deferred |
| Restarting ISPmanager panel daemons with `kill` | panel state corruption | `mgrctl -m core --restart srvparam` |

## Forbidden

- Deleting files that the task does not mention, without explicit owner consent.
- Running `remediate.sh` without a preceding `detect.sh` (the before-state is mandatory).
- Forcing a package install when the authenticity gate has not passed.
- Enabling automatic upgrade or unattended reboot on a target host on your own initiative.
