docs(agents): HUB-1 — зелёный main и P0 из аудита для серверной сессии
Задание для серверной сессии Claude (не для agy): довести main до зелёного и закрыть P0 аудита Hermes Hub. Шаг 1 плана слияния — стабильный Hermes как эталон переноса. Причина красного main найдена ревьюером в логе CI, а не по аудиту: - test_a37_isolation_guards.py:394 — WorkspaceBoundaryGuard пропускает rm -rf $HOME/.hermes на Windows (провал security-инварианта); - verify_multi_provider_router.py:63 — UnicodeEncodeError на cp1252 при печати русского текста. Остальные P0 (Release Gate hash, publication gate fail-open, /api/action CSRF) — подтвердить исполнением перед правкой. pricing safe_dump — реальный, в P1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
144f6a5d59
commit
93da1b22fd
1 changed files with 150 additions and 0 deletions
150
agents/inbox/2026-09-02-HUB1-audit-p0-green-main.md
Normal file
150
agents/inbox/2026-09-02-HUB1-audit-p0-green-main.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# Задание HUB-1: зелёный main и P0 из аудита Hermes Hub
|
||||
|
||||
## Для кого
|
||||
**Серверная сессия Claude (пользователь `ochenstarik`), не для agy.** Это работа
|
||||
исполнителя-Claude: правка кода, прогон, пуш. Ревьюер (сессия на ПК) принимает.
|
||||
|
||||
## Дата
|
||||
2026-09-02.
|
||||
|
||||
## База
|
||||
`origin/main` (`144f6a5`).
|
||||
|
||||
```
|
||||
git fetch origin --prune
|
||||
git checkout -b hub/audit-p0-green-main origin/main
|
||||
```
|
||||
|
||||
В `main` напрямую не пушить. **Координация:** над `main` работают две сессии.
|
||||
Перед пушем — `git fetch` и `git log --oneline origin/main`; при расхождении
|
||||
перенести правки поверх, как это уже делалось.
|
||||
|
||||
## Зачем
|
||||
|
||||
По решению о слиянии (`docs/research/kagent-merge-decision.md`) шаг 1 —
|
||||
**Hermes довести до зелёного и стабильного**, потому что он служит эталоном
|
||||
переноса, а сломанный эталон портировать нельзя. Сейчас `main` красный. Полный
|
||||
аудит — на рабочем столе владельца (`HERMES_HUB_FULL_AUDIT_2026-09-02.md`);
|
||||
здесь только то, что подтверждено исполнением.
|
||||
|
||||
---
|
||||
|
||||
## Что ревьюер уже проверил — заново не выяснять
|
||||
|
||||
### CI на main красный. Причина — два дефекта, оба видны в логе последнего прогона
|
||||
|
||||
**1. Security-инвариант A37 не держится на Windows.**
|
||||
`tests/test_a37_isolation_guards.py:394` падает:
|
||||
|
||||
```
|
||||
AssertionError: команда со стильдой прошла мимо защиты: rm -rf $HOME/.hermes (OK)
|
||||
assert not True
|
||||
```
|
||||
|
||||
WorkspaceBoundaryGuard пропускает разрушительную команду с `$HOME`, потому что
|
||||
раскрытие переменных и нормализация путей на Windows и Linux различаются. Это
|
||||
не косметика — это граница вокруг агентских shell-действий. Пока она работает
|
||||
по-разному на поддерживаемых системах, sandbox нельзя считать доказанным.
|
||||
|
||||
**2. Windows UTF-8 роняет verification-скрипт.**
|
||||
`scripts/verify_multi_provider_router.py:63`:
|
||||
|
||||
```
|
||||
UnicodeEncodeError: 'charmap' codec can't encode characters ...
|
||||
```
|
||||
|
||||
Скрипт печатает русский текст (`[PASS] Чистая конфигурация...`), а консоль
|
||||
Windows в CI — cp1252. Падает `print`, не логика.
|
||||
|
||||
Красные джобы: `Headless Run (no GUI dependencies)` и
|
||||
`Clean Windows Runner Test`.
|
||||
|
||||
### Баг pricing fallback (P2, но реальный)
|
||||
|
||||
`src/antigravity_provider/router/telemetry_service.py:164`:
|
||||
|
||||
```python
|
||||
data = yaml.safe_dump(p.read_text(encoding="utf-8"))
|
||||
if isinstance(data, dict) and "pricing" in data: # всегда False
|
||||
```
|
||||
|
||||
`safe_dump` вместо `safe_load` — таблица цен из `pricing.yaml` не грузится
|
||||
никогда, и `except: pass` это глушит. Должно быть `safe_load`.
|
||||
|
||||
---
|
||||
|
||||
## P0-1. Зелёный main (это первично)
|
||||
|
||||
1. **Исправить UTF-8 в verification-скрипте**: принудительный UTF-8 вывода
|
||||
(`PYTHONUTF8`, `PYTHONIOENCODING=utf-8`, реконфигурация `sys.stdout`, либо
|
||||
безопасное кодирование). Кросс-платформенно, проверяемо на обеих системах.
|
||||
2. **Исправить WorkspaceBoundaryGuard** единым конвейером: классификация
|
||||
диалекта shell → раскрытие только распознанных переменных → нормализация
|
||||
разделителей → разрешение `$HOME`/`%USERPROFILE%` → канонизация пути →
|
||||
сравнение с защищёнными корнями → **fail closed**. Одинаковый тест-набор для
|
||||
Windows и Linux; `test_a37_isolation_guards` должен ловить `rm -rf $HOME/...`
|
||||
на обеих системах.
|
||||
3. **Проверка — по зелёному CI**, а не локально: локальный прогон на Linux эти
|
||||
две джобы не воспроизводит. Довести оба Windows-джоба до зелёного.
|
||||
|
||||
## P0-2. Остальные P0 аудита — подтвердить исполнением ПЕРЕД правкой
|
||||
|
||||
Ревьюер их не проверял. По каждому: сначала воспроизвести, потом чинить. Не
|
||||
чинить со слов аудита.
|
||||
|
||||
1. **Release Gate заявляет проверку хеша, которой не было** — частичный HTTP
|
||||
Range, но `PACKAGE_HASH_VERIFIED=True` без полного SHA-256. Прочитать
|
||||
`scripts/release_gate.py`, подтвердить, затем считать полный хеш или брать
|
||||
достоверный digest из release API.
|
||||
2. **Publication gate fail-open** — 404/сеть/отсутствие пакета возвращаются как
|
||||
PASS. Разделить Offline Gate (тесты, updater, статика, сборка) и Publication
|
||||
Gate (релиз есть, ассеты есть, digest сверен, скачивание прошло).
|
||||
3. **localhost `/api/action` без CSRF/Origin** — на loopback токен не требуется,
|
||||
а действие меняет состояние. Проверить, затем: bootstrap-токен, проверка
|
||||
`Origin`/`Sec-Fetch-Site`, авторизация небезопасных методов.
|
||||
|
||||
## P1. После зелёного main
|
||||
|
||||
1. **Zip-slip в updater**: распаковка обязана проверять каждый путь
|
||||
(`resolved.is_relative_to(staging)`), запрет абсолютных путей, `..`, symlink,
|
||||
device.
|
||||
2. **pricing fallback**: `safe_load` вместо `safe_dump` (см. выше).
|
||||
3. **CI-матрица Windows + Linux**: сейчас Linux-джоба нет, а проект на Linux и
|
||||
активно получает Linux-фиксы.
|
||||
4. Прочее из аудита (failover error policy, `uv sync --frozen`, лишний `web`
|
||||
extra, secret-scan шире) — отдельными заданиями, не в этом.
|
||||
|
||||
---
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Правки ревьюера из `main` не откатывать.
|
||||
- Фронтенд без npm/сборки/фреймворков — `docs/web-api/CONTRACT.md` §1.
|
||||
- Проверку SHA-256 и список разрешённых адресов обновления не ослаблять.
|
||||
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
|
||||
- Версию `0.1.3` не понижать.
|
||||
- Правило честности: неизмеренное — `Н/Д` с причиной.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
1. Ветка в `origin`, `git status` чист.
|
||||
2. **Оба Windows-джоба CI зелёные** — ссылка на зелёный прогон в отчёте.
|
||||
3. `test_a37_isolation_guards` ловит `rm -rf $HOME/...` на Windows и Linux;
|
||||
guard fail-closed.
|
||||
4. verification-скрипт не падает на cp1252.
|
||||
5. Остальные P0 либо исправлены с доказательством, либо явно помечены как
|
||||
отложенные с причиной.
|
||||
6. `ruff check .` чисто; локальный прогон Linux зелёный; число тестов не меньше
|
||||
текущего.
|
||||
7. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`,
|
||||
`X passed / Y skipped / Z failed`, ссылка на зелёный CI.
|
||||
|
||||
## Главное
|
||||
|
||||
Первично — зелёный main, и обе причины уже найдены: security-guard на Windows и
|
||||
UTF-8 в verification. Остальные P0 аудита — только после подтверждения
|
||||
исполнением. Это фундамент под слияние: пока Hermes красный и его sandbox-guard
|
||||
дырявый на одной из систем, переносить его поведение в KAgent нельзя.
|
||||
|
||||
## Порядок сдачи
|
||||
Передать точный `FINAL_COMMIT_SHA` и ссылку на зелёный прогон CI.
|
||||
Loading…
Reference in a new issue