diff --git a/docs/superpowers/plans/2026-06-03-router-mentor-machine-1-foundation.md b/docs/superpowers/plans/2026-06-03-router-mentor-machine-1-foundation.md index 9f39913a..5e101eca 100644 --- a/docs/superpowers/plans/2026-06-03-router-mentor-machine-1-foundation.md +++ b/docs/superpowers/plans/2026-06-03-router-mentor-machine-1-foundation.md @@ -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):** A1–A4.