docs(m1): аудит Машины 1 — хвосты (A1-A4) + замечания (B1-B4) + фикс-сет

This commit is contained in:
Дмитрий
2026-06-05 03:40:13 +03:00
parent 1d676a5616
commit 35a569d370
@@ -1006,3 +1006,27 @@ git commit -m "test(m1): foundation cross-invariants (journal tamper / unsigned
## СЛЕДУЮЩИЙ ШАГ
План Машины 1 готов. Исполнение — `superpowers:subagent-driven-development` (свежий субагент на задачу + двухстадийное ревью) ИЛИ `superpowers:executing-plans` (встык в этой сессии с чекпойнтами). По завершении М1 и полной регрессии — детальный план Машины 2 (Замок плана + Верховный хук), который ПОТРЕБЛЯЕТ журнал и расписки этого фундамента.
---
## АУДИТ МАШИНЫ 1 (2026-06-05) — хвосты + замечания + фикс-сет
Адверсари-сверка построчно (10 задач плана + несущие №1/№5 + P10-a/b/c). **Все 10 задач собраны точно, полная регрессия 2222 GREEN, внутренняя логика модулей цела.** Хвосты — это граница слоёв (A) + непреднамеренные зазоры аудита (B).
### A. Сознательно отложено (граница слоёв — НЕ дыры)
- **A1.** Enforcement «нет записи → нет действия» → **Машина 2** (верховный хук читает журнал). M1 = только примитив записи + verify (записано в шапке `action-journal.mjs`).
- **A2.** Реальное потребление журнала/расписок (кто пишет ДО действия, кто читает расписки) → **Машины 2/4**. M1 — библиотека-фундамент.
- **A3.** `resolveReceiptKey` в проде M1 не вызывается — провайдер ключа для потребителей M2/M4 (Self-Review плана: осознанный зазор, не мёртвый код).
- **A4.** HMAC-ключ расписок провижинит **владелец** (keychain `router-mentor-receipts` / env `ROUTER_MENTOR_RECEIPT_KEY`); без ключа подпись=null, verify=false (fail-closed). Owner-шаг.
### B. Замечания аудита (непреднамеренные — план их не признавал)
- **B1** `[owner-шаг]`**P10-a живёт наполовину.** `decide` toolName-агностичный (ловит любой path-bearing tool), но живой хук-matcher узкий (`Edit|Write|MultiEdit|NotebookEdit`, заголовок файла) → MCP-писатель `mcp__fs__write` хук не вызовет. Цель «ловить MCP» в проде не работает, пока владелец не расширит matcher в `.claude/settings.json` (или `*`). Код готов.
- **B2** `[ИСПРАВЛЕНО 2026-06-05]``ts`/`seq` промежуточных записей журнала были ВНЕ `chain_hash` → подделываемы без детекта. Фикс: `chain_hash` теперь над `{seq, ts, payload}` (подмена ts/seq ломает цепь).
- **B3** `[→ требование к Машине 2]` — откат журнала (атакующий кладёт старую валидно-подписанную пару `.jsonl`+`.head`) `verifyChain` не ловит. Нужен внешний монотонный счётчик / high-water-mark в enforcement Машины 2.
- **B4** `[ИСПРАВЛЕНО 2026-06-05]``extractPath` знал 4 поля → MCP с полем `filename`/`uri`/`destination` проскальзывал. Фикс: список путь-полей расширен.
### Статус фикс-сета
- **Исправлено кодом (TDD):** B2 (`action-journal` — seq+ts в хеше), B4 (`enforce-runtime-write-deny` — расширены path-поля).
- **Owner-шаг:** B1 (расширить matcher хука в settings.json — иначе P10-a не ловит MCP вживую).
- **Требование к Машине 2:** B3 (анти-rollback монотонный счётчик).
- **Граница слоёв (не трогать в M1):** A1A4.