401 KiB
MCP: подключение и состояние реализации
Актуальное состояние на 3 ноября 2026: план и оставшиеся направления, машиночитаемый статус. Linux-приёмка обслуживания БД прошла16 сценариев; текущий reader принят на двух CHR без изменения конфигурации. Порядок ручной проверки после неопределённого восстановления. Полный план, полная двухузловая схема и лимит всей установки2ГБ остаются открыты. Числа и разрешённые окна в прежних датированных срезах ниже являются историческими.
Состояние на 29 октября: speed-test 3/3 и manual collectors 4/4 завершены; REST: 200 mediated / 62 excluded / 0 pending. Весь план: осталось 7 направлений. Приняты локальные NetFlow worker/services и компоненты routing forward rounds/private handoff. Полный autoRecovery, внешняя сетевая приёмка и нагрузка ≤2 ГБ остаются открыты. Текущий реестр, последняя приёмка routing.
29 октября — подготовлен фиксированный key/HMAC-примитив для OP-M4. Локальный отчёт: 42 точечные проверки, независимый review, полная peer-регрессия, build и строгая проверка типов прошли. Чтение ровно 32 байт и HMAC выполняются без await; проверяются текущий hash/inode, исходные actor/owner signals и wall/monotonic deadline, scratch key очищается до close. Примитив пока не подключён к dispatcher: он не удостоверяет Q/права/подписанный источник и не сокращает старую цепочку проверок. Полная same-owner цепочка, measured-latency positive и реальное окно ещё открыты. OP-M: 3/4, S3: 5/10. Новых процессов/pool/миграций нет; оставшееся окно стенда сохранено, нагрузочная приёмка всей установки ≤2 GB не завершена.
29 октября — OP-M3 принят как компонент, готово 3/4 шагов окна. Guarded managed/external sources: 57 focused tests, 9 actual PG/localhost групп, 24 legacy PG-группы, native 77/77; полные peer/storage-наборы и build прошли. External metadata работает без key file и проверяет current encrypted profile/generation/directory; оба sources требуют genuine original-window guard. Реальный race HELD → потеря owner во время Q воспроизведён и исправлен через непрерывный lifetimeSignal connector → core → node → window. Последний внутренний шаг OP-M4 открыт: fixed effects на том же PID, положительная measured-latency и эксплуатационная приёмка. S3: 5/10 закрыто, 5 осталось. Окно стенда не использовано; текущий operating-срез сохраняет полный план и требование всей установки ≤2 GB.
28 октября — managed metadata OP-M3 принят как компонент. 29 новых тестов и 4 actual PG/localhost-сценария: genuine observation/prerequisite и текущий signed grant проверяются без повторной выдачи credentials, Q или native. SQL сравнивает исходные private endpoint/password внутри PostgreSQL и возвращает boolean; неверные значения отклоняются даже при неизменном epoch. Штатный endpoint trigger сохранён: восстановление полей не оживляет старый origin. Build и полный peer-набор прошли. External provider пока отсутствует и отказывает без fallback, OP-M3 открыт. Готово по-прежнему 2/4 внутренних шага окна; S3 5/10 закрыто, 5 осталось. Одно окно стенда сохранено; весь MCP-план и ≤2 GB RAM остаются открыты.
28 октября — same-lease metadata принят как компонент. 19 новых тестов и 7 actual PostgreSQL-сценариев подтвердили работу без secret files, исходные role/catalog/source validators, точный PID/exclusive lock, отказ конкурента и физическое закрытие при abort/busy/drift. Дополнительные pool/роль/миграция не созданы. Build и полный peer-набор прошли. В остатке operator window теперь 2 из 4 внутренних шагов готовы: OP-M1 public files и OP-M2 public same-lease inspection; OP-M3 private endpoint metadata и OP-M4 fixed effects/latency/stand acceptance открыты. Это не закрывает S3-06: основной счётчик 5/10, осталось 5, одно окно стенда сохранено; весь MCP-план и ≤2 GB RAM открыты.
28 октября — public metadata prerequisite реализован. 17/17 новых тестов и актуальная регрессия: core/node читают только свежие подписанные публичные файлы, не получают ключи/credentials или SQL lease и не создают strong authority. Настоящая configured core → node композиция v1/v2 проверена; backend build и полный peer-набор прошли. Это завершённый внутренний шаг S3-06, а не готовое operator window. Далее нужны fixed same-lease metadata session, private current endpoint/credential commitment proof и fixed effect dispatcher с измеренной latency-приёмкой. Точный effect ledger сохраняет обе HMAC-фазы и реальные before/after границы. S3: закрыто 5/10, осталось 5; одно разрешённое окно сохранено, общий MCP-план и ≤2 GB RAM открыты.
28 октября — текущий operating/performance-срез. Диагностический v7 прошёл получение Docker quiescence и открытие source, затем отказал в registry SQL; точная SQL-причина не установлена. Независимый watchdog восстановил исходные policy/running и health 200. Последующий read-only postflight подтвердил четыре исходных контейнера и отсутствие всех 17 временных путей. Из двух дополнительно разрешённых окон использовано одно; одно осталось и не расходуется до положительной локальной проверки с измеренными задержками Docker. Полный пятиконтейнерный scan оценён в 464,748 ms; прежние 308 scans требуют около 143 секунд при неизменном допуске 5 секунд. Объединение парных inspect/authorize и параллельное чтение публичных файлов прошли unit-проверки, но производительность композиции ещё не принята: realistic-latency профиль отказал до credentials/COMMIT, без действий с backend. Последние backend build и полный peer-набор прошли. Текущий отчёт, непринятый проект изменения контракта. S3 остаётся 5/10; полный план и требование всей установки ≤2 GB сохраняются.
28 октября 2026, следующий компонентный срез: genuine MCP speed — 6 owned SQL/HTTP-групп, writer/kernel/fixed native — 31 группа, native-регрессия — 77 тестов. Публичный speed action и все runtime callers ещё открыты. В план добавлено требование вся установка с MCP ≤2 GB RAM, методика измерений и кандидат Compose; нагрузочное соответствие пока не подтверждено. Два однократно разрешённых operating-прогона завершились отказом, следующий подготовленный пакет сам по себе разрешения на запуск не даёт. Текущий S3 остаётся 5/10, полный план не завершён.
28 октября 2026, текущий интеграционный срез: router guard, три full-speed original и durable run ID. Приняты 18 guard SQL/HTTP-сценариев, v1/v2 same-control compatibility, scheduler 6 и REST 7 SQL/TCP-групп, 6 workflow + 4 run-ID SQL/HTTP-сценария. MCP original unit 14, workflow/run identity 41, native 70; build/TS/lint/auth/full MCP/speed baseline прошли. Новые компоненты не включают runtime all-callers или публичный MCP speed action; положительный MCP SQL/HTTP-профиль ещё нужен. Этап остаётся 5/10, точный оставшийся объём.
28 октября 2026, дополнение: общий speed workflow прошёл 6/6 сквозных owned PostgreSQL/HTTP-сценариев: genuine REST/JWT, signed execution host, completion receipt, пауза, after-ping и история. Проверены потеря возврата COMMIT и native socket drop с unknown без replay. Scheduled speed provider реализован и unit-проверен. Enrollment Q и wire mapping этого профиля синтетические; все callers и публичный MCP speed action ещё не включены. Текущий счётчик остаётся 5/10, весь MCP-план открыт. Актуальный трекер.
28 октября 2026: scoped bandwidth SQL/HTTP-приёмка прошла: v1 25 сценариев с dump/restore, повтор v2 23 сценария / 89 license GET / 2 btest POST; native 57/57 и полный peer script — exit 0. Настоящий SQL/transport barrier и operator writer lifecycle приняты как компоненты. Текущий speed-test этап: закрыто 5/10, осталось 5; внешний stop/restart issuer, wire mapping, все callers, публичный speed workflow и финальная приёмка ещё открыты. Трекер, полный оставшийся объём.
2026-10-26: полный server poll принят через публичный MCP. Инструмент mm_server_poll_plan требует человеческого подтверждения; сохраняет исходный допуск, использует ограниченный журнал и возвращает безопасный снимок. Сквозная приёмка с обслуживанием истории завершилась за 151506 ms при лимите 180 секунд; проверены read-only квитанция, отсутствие повторного native и точное восстановление журнала. Каталог: 358 инструментов; 195 mediated / 62 excluded / 5 pending. MCP admissions owner8/global128 удерживаются до retention GC; это не лимит одновременных запросов. Штатный UI REST handler сохранён. Актуальные оставшиеся задачи и критерии приёмки.
2026-10-26: повторная приёмка экспорта существующих IPsec-сертификатов прошла для client/server/other/CA через REST, MCP с человеческим подтверждением и портал владельца. Явные private/CA-флаги обязательны; модель получает только квитанцию, зашифрованный файл доступен владельцу 15 минут. Выполнены только синтетические проверки, без деплоя и реальных ключей CHR. Этот статус заменяет исторические записи ниже о выключенной активации или ожидаемом разрешении.
Poll-storage устанавливается штатной0039 и обслуживается worker. Дважды выполнен реальный startup39; непустой старый журнал сохраняется с отказом до DDL. Independent reference и18pristine seeds проверены. Существующий worker выполняет ограниченный GC даже при отключённом MCP; реальные expired rows/atomicrefund и9lifecycle-unit прошли, новый timer не добавлен. Сам SQL predicate теперь держит retention setting FOR SHARE: прямой guarded DELETE также защищён от гонки с увеличением срока хранения.12SQL-lifecycle случаев, quota-bound4GET/fullmaintenance, два current39 dump/restore с7-табличной сверкой,6публичных диагностик и4роли IPsec/CA прошли. Public poll пока не подключён: нужны read-only receipt verify/reconcile, sealed human-approved MCP binding иwhole current-authority/REST приёмка. Storage128/8 — лимиты сохраняемых admissions доGC, а не concurrent slots; рабочую ёмкость необходимо проверить перед заменой REST. Coverage357/194mediated/62excluded/6pending; деплоя не было.
Отдельно на current39 повторён полный148-effect сценарий с удалением истёкшего partition:4nativeGET,152публикации, ordinary writer блокируется доrelation SQL, known replay иlate revoke безновыхnative; настоящий dump/restore/tamper прошёл. Этот сценарий также использует новый quota-bound constructor.
Квоты и безопасная очистка полного poll проверены: до anchor подтверждается отдельный резерв8MiB+32KiB, максимум128попыток глобально и8на владельца. Существующий admission не получает новый claim token. Новый quota-bound исполнитель прошёл4nativeGET,147maintenance/151публикацию и312metered journal rows; replay не вызывает native и не расходует квоту. Настоящие lost COMMIT ACK, orphan quarantine, конкурентные лимиты, полный GC/atomicrefund и запрет удаления одним GUC прошли10SQL-сценариев. После реального dump/restore совпали все7таблиц, включая ciphertext/claim tokens; global/owner counters сверены,128-attempt cap сохранился.36новыхunit +regression/strict/lint/build прошли. Схема пока isolated proposal: штатная миграция, worker hook и public poll/actual sealed MCP-plan/current authority acceptance ещё впереди; normal manifest38 и coverage357/194mediated/62excluded/6pending не менялись. Новая private REST factory использует quota-bound session и без этой схемы отказывает; действующий публичный REST route не заменён. Деплоя не было.
Полный server poll: схема и внутренний исполнитель проверены. Штатная0038 устанавливает журнал и writer guards; общий manifest/reference теперь содержит38миграций, исторические fixtures остаются на0036. На временной БД прошли4nativeGET,148maintenance-действий,152публикации, исключение конкурентного writer до обращения к relation, повтор без native и настоящий dump/restore. Общий предел poll180s включает журнал/DDL; native15s, SQL5s и исходный срок допуска сохранены. Новые authority/REST factories прошли18unit-сценариев, но публичный poll ещё не подключён: нужны квота/retention журнала, real approved MCP-plan wiring и сквозная SQL/HTTP-приёмка именно этих factories. Экспорт существующих IPsec/CA повторно прошёл все4роли и owner portal на синтетических ключах. Coverage остаётся357/194mediated/62excluded/6pending; деплоя не было.
Диагностика теперь доступна через рабочие REST/MCP адаптеры: public tools mm_server_probe_plan (6видов диагностики и human approval), mm_server_probe_receipt_get (страницы с текущим read-допуском) и mm_server_probe_cancel (немедленный stop с write-проверкой). REST использует тот же журнал/квоты, retention подключён к существующему worker. Все6команд, реальные локальные DNS UDP/TCP, большие страницы, отмена до/во время send и actual app/JWT проверены. Сетевые лимиты сохранены; проверки доступа/сохранение получили ограниченный30s reserve без продления private expiry. Coverage теперь 357tools/194mediated/62excluded/6pending. На удалённый стенд изменения не развёртывались; общий DB-control, legacy-backfill и прочая приёмка полного плана ещё не закрыты.
Первичная схема v2 теперь устанавливается штатной0037: migration выполняется только при пустом legacy, непустые данные сохраняются с отказом до DDL. Проверены повторный startup, MCP/REST runtime на новой схеме и настоящий dump/restore. Legacy fixtures явно остаются на0036; для них нельзя фабриковать0037marker. Production adapters и retention lifecycle ещё не подключены; публичных pending остаётся7. Деплоя на стенд не было.
Проверено состояние первой установки на стенде: таблиц MCP/server_probe ещё нет, все новые MCP-миграции пока находятся в worktree. Следующее подключение пойдёт через fresh-only v2 migration с отказом при непустом legacy; отдельный backfill остаётся для промежуточных dev-установок и restore. Никаких удалённых изменений не выполнялось.
Legacy MCP orphan-приёмка прошла на настоящем PostgreSQL: completed receipt, карантин без anchor и отмена без anchor проверены по реальному sealed source с истёкшим original credential. Из8 записей3 подтверждены,5 отклонены; чтение не меняет immutable rows, v2 не устанавливается и native не вызывается. generationAuthenticated/migrationReady/conversionAllowed остаются false.
Источник и legacy snapshot связаны внутренней проверкой: данные журнала и source facts читаются на одном owned backend/transaction/snapshot с проверкой до и после. Нельзя заменить observation JSON-копией или перенести на другой SQL facade. На временном PostgreSQL проверены source/data pairing, различие двух БД одного кластера и защита от shadow type/operator через search_path. 20 новых тестов и связанная регрессия прошли. Исходные идентификаторы остаются внутренними; generationAuthenticated/READY/conversionAllowed=false. Независимое поколение источника, backfill и безопасное переключение ещё не реализованы.
Внутренняя операторская проверка legacy защищена и принята: актуальные права администратора проверяются до чтения и повторно на свежем backend после snapshot. JWT/app/scope не задаются JSON тела; callback и SQL ограничены сроками и отменой, поздний client закрыт. На настоящем PostgreSQL проверены отзыв прав между сбором/выдачей и отмена при удерживаемом relation lock; общая регрессия прошла. Публичный route не зарегистрирован, migrationReady/conversionAllowed=false. Следующие условия подключения — source DB authority, backfill и writer/DDL drain.
Исторические квитанции и согласованный read-only снимок проверены: verifier различает authenticated receipt, approved original MCP source и context-only quarantine; недостаток доказательств блокирует перенос. Collector не возвращает отдельные идентификаторы или payload, требует явную read-only repeatable-read transaction и обнаруживает лимиты/неполноту. Реальный PostgreSQL подтвердил неизменность текущего snapshot при параллельном legacy writer и появление новой записи в следующем; original expired MCP source доступен без возобновления старых прав. 69+20 новых проверок и полная связанная SQL/HTTP/restore-регрессия прошли. Это внутренние компоненты: lifecycle/текущие права оператора принадлежат будущему host. Во всех результатах migrationReady/conversionAllowed=false; публичный переход схемы, backfill и writer/DDL drain не выполнялись.
Управляемые metadata/owner проверки теперь отменяются: отдельный контекст запроса ограничивает owned SQL и callbacks, а поздний client не может продолжить работу после закрытия родительского окна. Проверка на настоящем PostgreSQL lock подтвердила завершение factory и HTTP/JWT handler до снятия блокировки, без native-вызова и admission. Независимый quarantine сохранён. Финальные runtime/regression/restore проверки прошли. Общие runtime/watchers и чужие planner transactions сохраняют свои правила; переключение production route и authenticated переход схемы v2 ещё не выполнены.
REST-подключение к v2 подготовлено и проверено: новый factory и отдельный HTTP plugin используют общий журнал, квоту и карантин, сохраняя ответ {output}. Проверены реальные JWT, запрет подмены идентичности, отключение клиента, BW fallback и работа без перечисления парка из 1001 сервера. Сквозной MCP runtime после выделения общего I/O также проходит приёмку. Это opt-in исходники: production startup пока использует старый REST route, переход схемы и публичное подключение ещё не выполнены. Полная native-проверка всех шести инструментов и bounded outer metadata/authority SQL остаются отдельными пунктами readiness.
Внутренняя сборка run/read/cancel проверена: реальный MCP runtime с подтверждением человека выполнил диагностический запрос к HTTP127, сохранил отдельный encrypted payload и выдал модели только квитанцию. История доступна новому read-only токену с исходной привязкой. Отмена уже отправленного второго запроса закрыла socket; два cancel дали один audit и quarantine без результата, повторной отправки не произошло. Проверены короткие SQL/cleanup budgets и срок private prepared plan для длинных измерений. Исторические SQL snapshots теперь используют bounded connector. Все относящиеся проверки прошли; source factory не регистрирует публичные tools/routes. Production-переход схемы v2 и публичное подключение пока не выполнены.
Диагностические SQL-компоненты проверены: источник и назначение можно читать через backend, принадлежащий storage host; native/crypto implementations остаются штатными. Отдельный connector соблюдает отмену и сроки ожидания соединения/запроса, уничтожает неопределённое соединение и допускает независимую запись карантина через новый lease. Пройдены 24 новых unit tests, 6 driver SQL-сценариев, 22 journal SQL-сценария, production prepare/preflight на одном backend, dump/restore/tamper и полный management profile. Это opt-in компоненты; общий runtime host и публичное подключение v2 ещё открыты.
Исправлена запись карантина неопределённой диагностики: потеря подтверждения уже сохранённого результата больше не позволяет обойти карантин из-за отмены исходного запроса, его deadline или смены настроек. Отдельный ограниченный cleanup сохраняет точную scope/identity-привязку и не создаёт новых попыток или результатов. Пройдены 11 model и 22 SQL-сценария, dump/restore/tamper, диагностическая регрессия, build/types/lint. Это opt-in v2 source; public registration и production enrollment ещё не завершены.
Экспорт существующих IPsec-сертификатов активирован после отдельного разрешения: общий guarded REST/MCP путь работает для client/server/other/CA. REST требует вход, network-write, явный private intent и UUID запроса; CA — отдельный флаг. MCP требует человека и отдаёт модели только квитанцию, файл владельцу доступен 15 минут. Старые export bodies/fallback удалены. Штатные assemblies прошли SQL/HTTP/portal/dump/restore/tamper, 5 API и 7 browser checks, MCP/IPsec/model profiles, build/type/lint. Покрытие: 354 инструмента; 193 mediated /62 excluded /7 pending из 262 REST routes. Реального экспорта CHR и деплоя не было; native, routing, diagnostics и остальные пункты полного плана ещё открыты.
Принят разрешённый cancellation host: одобренный патч применён, 17 настоящих SQL-сценариев, профиль диагностики и dump/restore/tamper прошли. Текущие права, исходная операция, отмена, аудит и общая reservation проверяются одним backend; повтор не удваивает audit/quota. Проверены rollback, lost COMMIT ACK и гонки с claim/завершением. Новая защита сервера сохраняет право владельца остановить уже идущую работу; это не разрешение native-записи. API не зарегистрирован, рабочая БД и CHR не затронуты.
Сквозная приёмка IPsec export UI/REST/MCP/портала: интерфейс запрашивает private/CA consent до POST, передаёт один UUID на подтверждённую попытку и отменяет pending fetch при закрытии. 5 API и 7 браузерных тестов, 41 HTTP mapping model case и реальная SQL/HTTP-композиция с обоими selector и всеми четырьмя ролями через REST и MCP прошли. Проверены human approval, encrypted artifact, owner-only portal/listing/TTL, unknown/no-replay, revoke/cancel и настоящий dump/restore/tamper. Штатный registrar и REST переключение подготовлены за выключенным existing/CA flag, публичное покрытие ещё 353 /191/62/9. Приёмка использует только подставной RouterOS/PKCS12; реальный экспорт ключей и деплой не выполнялись.
Получено отдельное разрешение на cancellation host: проверенный tmp/mcp-diagnostic-cancel-host-reviewed.patch применён. Регистрации API нет; его отдельная транзакционная приёмка выполняется только на временной PostgreSQL.
Общий executor IPsec-экспорта и закрытые REST/MCP assemblies: native export/read/cleanup теперь выполняются одним алгоритмом. REST использует реального пользователя и opaque одноразовый token; MCP сохраняет совместимую sealed authority и выдаёт только квитанцию. Прошли 48 REST-модельных и 14 настоящих SQL-сценариев журнала, включая конкуренцию, потерю COMMIT ACK, отзыв после реального ожидания lock и порядок checkpoint 1→2; dump/restore/tamper, полный MCP, build/type/lint тоже прошли. Портал распознаёт новый artifact kind; при закрытом feature gate запрос останавливается до шифротекста/native I/O. Действующие REST export handlers пока не переключены, новые MCP tools не зарегистрированы, флаг existing/CA export остаётся false. Полный план и 9 pending не закрыты.
Подготовлен закрытый адаптер экспорта существующих IPsec-сертификатов: оба REST selector, human-only план, sealed binding без самоссылки inputProof, строгая квитанция и read-only сверка с VERIFIED step/artifact проверены на синтетических зависимостях. Публичной регистрации и включения экспорта существующих/CA-ключей нет. Исправлено затирание приватных Buffer в reader, CREATE и закрытом executor при отказе, смене состояния и позднем ответе после отмены; 10 проверок очистки и профили RouterOS files/IPsec/pending foundations прошли. Полный план и 9 pending остаются открытыми.
Связка реальных adapter/executor проверена с подставным I/O, включая inputProof на durable claim и запрет повторной отправки. Новый test:mcp:ipsec-create:pg прошёл SQL/HTTP CREATE и настоящий terminal restore/tamper с явным MMAPP_PG_CLIENT_BIN. В первом широком запуске все SQL-этапы прошли, но финальный restore не нашёл pg_dump; этот отказ сохранён отдельно, а успешный focused run не подменяет его код завершения.
Принято сравнение данных реального MCP-восстановления: на собственной временной PostgreSQL содержимое 97 таблиц и 8 sequences совпало с архивом после миграций, до запуска фоновых задач. После запуска отдельно проверены связь архива с владельцем/операцией и единственная точная запись аудита. Никакие таблицы из сравнения не исключались. Исправлены лишний пустой flush свежего/reset Traffic Flow engine и запуск выключенного коллектора при завершении операции БД. Прошли 13 SQL-сценариев inventory, terminal restore/tamper, SQL-регрессия Flow, полные system-database и Flow ownership profiles, 14 lifecycle-тестов и build. ESLint: 0 ошибок, одно существовавшее предупреждение. Проверка остаётся тестовым evidence; production READY, cancellation host, деплой и изменения CHR не включены. Полный план ещё не завершён.
Принят read-only data inventory: 15 модельных и 13 SQL-сценариев, включая реальное равенство содержимого и sequence после pg_dump/pg_restore, native array bounds, дубликаты, лимиты и внешнюю mmapp_control. Данные хешируются потоково, сырые строки не выдаются; views не исполняются. Full system-database profile, build, lint и terminal restore/tamper прошли. Подписанный issuer/reference и quiescence ещё не реализованы, READY остаётся false. Отложенный cancellation host не применялся, рабочая БД и CHR не менялись.
Проверены SQL-предпосылки cancellation host: 8 сценариев зашифрованного источника и текущих grants, включая терминальные rejected/partial, вместе с прежними 17 storage/GC-сценариями и настоящим dump/restore. Подготовленный host-патч прошёл статическую проверку и review, но пока не применён: автоматическая проверка потребовала отдельного разрешения на запись отмены/аудита через настроенный pool. Его runtime-композиция ещё не проверялась; регистрации API и деплоя нет.
Принят разрешённый GC диагностики: 17 SQL-сценариев удаления только истёкших служебных записей с защитным интервалом и текущим retention, плюс 12 сценариев reader истории и настоящий dump/restore/tamper. Свежий карантин и работающая операция блокируют удаление; rollback и потеря ACK проверены. Планы, операции и общий аудит сохраняются. Отмена использует одну reservation с выполнением, без двойного возврата квоты; повторная отмена больше не дублирует audit. Production-схема, worker и public registration ещё не включены; очистки действующей БД и изменений CHR не было.
Принят отдельный reader истории диагностики: 12 SQL-сценариев с исходным истёкшим MCP credential и новым текущим read-допуском, 42 исторических теста и 4 проверки deadline/abort. Reader схемы v2 сохраняет исходную identity и envelope, проверяет admission и раздельные proofs, различает expired/unavailable и повторно читает карантин/purge после расшифровки. Конкурентный отзыв credential блокирует выдачу. Полные MCP/diagnostics profiles, build, lint и настоящий dump/restore/tamper прошли. Подключение production-схемы v2 и регистрация диагностики остаются отдельными незавершёнными пунктами; деплоя и metadata GC не было.
Этап общего сетевого контекста, эталона схемы и хранилища диагностики: приняты независимый подписанный эталон 36 миграций и текущая проверка схемы/начальных данных (8 SQL-сценариев), общий бюджет configuration bridge и native snapshots (15 HTTP-тестов, 14 SQL/HTTP-сценариев, 126 запросов без native writes), а также опциональный storage adapter журнала (7 SQL-сценариев). Полный scoped prepare/approval/apply с genuine CONFIG_APPLIED, настоящий dump/restore/tamper, профили MCP/system-database/диагностики/native readers, build и scoped lint прошли. Production DDL, metadata GC, READY и автоматический сетевой inverse не включены. Полный план и 9 pending остаются открытыми.
Новый этап controlled migrations и genuine configuration bridge: 8 настоящих SQL-сценариев в 7 отдельных БД, два полных исполнения 36 закреплённых файлов и настоящий dump/restore/tamper прошли. Fixed dispatcher сохраняет intent до SQL, использует exclusive session lease на том же application backend, не переписывает self-managed файлы, проверяет COMMIT command tag и markers, затем сохраняет purpose-separated HMAC квитанцию. Потерянный ACK application COMMIT запрещает повтор; если потерян только ACK публикации уже подтверждённой HMAC-квитанции, новая invocation проверяет prefix и продолжает со следующего файла. Подмена hash одновременно в singleton/history не проходит. Это опциональный внутренний dispatcher: default startup не изменён, READY и schema/data verification не выдаются; актуальная полная сверка схемы/данных и quiescence всех writers перед activation остаются открыты.
Genuine configuration bridge проверен в полном scoped SQL/HTTP-профиле через prepare/approval/apply: revision-3 persistent manual request и реальный CONFIG_APPLIED, текущий raw owned rule/dependencies, одноразовый WeakMap context и повторный read-back на consume. JSON-копия, close, отключение профиля и подмена checkpoint блокируются без новой native-записи; autoRecovery guard сохранён. 30 bridge и 10 dispatcher модельных тестов, native профиль 210 тестов, system-database профиль, backend build и scoped ESLint прошли. Bridge пока использует отдельный ограниченный context reader: общий network budget и per-round full proof этим не доказаны, assembly и automatic inverse не подключены.
Дополнительное read-only наблюдение CHR подтвердило forwarding-enabled=no и www port 80 на первом CHR. Второй CHR отклонил новый SSH-вход до чтения настроек; повторов и изменений конфигурации не было. Полная recursive/forwarding-приёмка остаётся открытой. Деплоя, production DDL и новых публичных инструментов нет; полный план и 9 pending не закрыты.
Новый этап durable schema control, archive boundary и native assembly: на временной PostgreSQL прошли 14 сценариев в 9 отдельных БД, включая конкурирующих владельцев, три потери ACK реального COMMIT, restart quarantine, подмену истории, сохранение control вне public, настоящий pg_dump/restore и отказ архиву с control objects. REST и MCP export теперь исключают mmapp_control; общий restore проверяет TOC до SQL decode и target replacement. Это защита пространства управления, а не проверка произвольного SQL внутри архива. Production control tables/startup/dispatcher ещё не подключены; READY не выдаётся из caller JSON или равенства схемы.
Native assembly получила 23 теста и проверена на фактических baseline/двух forward/двух inverse снимках SQL/HTTP-reader: exact scope/source/phase/time и общий бюджет, strict parser для каждого этапа, явный UNKNOWN при отсутствии genuine configuration proof и log interval. Профиль native models теперь содержит 180 тестов; ещё 20 control, 3 archive boundary и 4 acquisition CLI теста прошли. Общие MCP/system-database профили, backend build и scoped lint прошли; все backend-профили не повторялись.
Read-only попытка сбора native recursive evidence с CHR: SSH к стенду и обоим CHR подтверждён по прежним pinned host keys; оба первых REST GET через временные двойные SSH-туннели завершились без response-body, без повторов и изменений конфигурации. Причина не установлена, raw route/nexthop samples не получены. Ограниченный протокол сбора и CLI готовы; undocumented numeric joins остаются unknown. Это не приёмка recursive convergence или трёхузлового forwarding. Деплоя и production DDL не было; полный план и 9 pending остаются открытыми.
Новый этап native readers и проверки схемы: 154 модельных теста, 14 SQL/HTTP-сценариев (99 запросов, 0 native writes) и 17 SQL-сценариев schema inventory прошли на изолированном стенде. Обе SQL-приёмки включают настоящий dump/restore и отказ для подменённого архива. Настоящий loopback HTTPS проверил DNS pin, сохранение Host/SNI, доверенную CA, отказ при неверном имени и недоверенной CA. Полный MCP-профиль, существующие server connection tests, backend build и scoped ESLint прошли.
Reader закрепляет текущие полномочия и endpoint, использует один транспорт и общий абсолютный бюджет ≤120 секунд: 1 MiB/ответ, 8 MiB суммарно, 256 запросов, 1000 строк/ответ и 10000 суммарно. Baseline и по 2–3 раунда forward/inverse не сбрасывают лимиты. Подтверждённый ping 3/0 не запускает traceroute. Парсер принимает точный native BGP session ID и прямой next-hop; recursive next-hop и полнота log interval остаются unknown. Это внутренний read-only слой с securityProof:false: подписанный полный checkpoint и автоматический inverse не включены. Process-local запрет повторного reader имеет предел 1024 source operations и не заменяет durable runner admission после рестарта.
Новый PostgreSQL 18 comparator сравнивает логическую схему независимо мигрированных БД, отдельно сохраняет и проверяет physical fast-default metadata, отказывается при неподдерживаемых объектах и внешних зависимостях. Реальная SQL-проверка обнаружила и закрыла пропуск зависимости view через pg_rewrite. Равенство DDL не доказывает эквивалентность данных и не разрешает enrollment. Durable startup recovery/control namespace и подключение comparator к dispatcher остаются открыты. CHR, production БД и деплой на этом этапе не затронуты; 9 pending не изменились.
Актуальный реестр: 353 инструмента; 191 mediated / 62 excluded / 9 pending из 262 REST-маршрутов. Полный план остаётся открытым. Проверки, хеши исходников и границы приёмки: протокол сетевого управления.
Предыдущий протокол common poll и reservation store: полный private poll assembly прошёл actual SQL/loopback HTTP — 4 GET, 148 maintenance effects всех 12 parents, 152 публикации и настоящий dump/restore/tamper. Одна фабрика связывает journal, production IO и maintenance lease с одним SQL backend; writer останавливается до relation SQL, повтор не отправляет GET, подмена input/подписи и отзыв блокируются. Предельные 120 секунд и полный maintenance сохранены; решения допуска не кэшируются. Отдельная приёмка выполнила 28 настоящих collector/FK-сценариев с 8 lock waits, 8 55P03 и 8 потерянными ACK реального COMMIT. Это внутренние entrypoints, не приёмка публичной HTTP-аутентификации или всех ручных MCP collectors.
Private reservation proposal/store прошёл 10 SQL-сценариев и dump/restore/tamper: 2 mutation units + 2 profile slots выделяются атомарно; manual/reserved inverse используют один source-step PK. Учитывается legacy switch history; capability для forward выдаётся только после нового подтверждённого COMMIT, read/repeated reserve/restart/JSON её не восстанавливают. После lost ACK capacity может остаться held без права продолжения; durable SQL unknown marker не заявляется. Refund и полный reserved inverse lifecycle ещё не реализованы. Runtime должен подключить store на том же transaction owner без двойного debit и согласовать controller accounting. Full poll HTTP/MCP routes, production migrations/triggers и controller пока не активированы; native/CHR/forwarding не заявляются. MCP-модели, адресные профили, build и scoped lint прошли. Счётчик pending прежний; предыдущие снимки ниже не заменяют этот протокол.
Предыдущий этап writer/routing integration: shared admission до SQL на том же backend подключён к 17 инвентаризированным группам записи, включая Drizzle/flow, collectors, FK cascade, partition DDL, миграции/import/psql restore и legacy CLI. CLI использует общий атомарный rebuild с квитанцией и ожиданием существующих writers. Отказ БД не создаёт ложное offline/down измерение; 27 проверок реального кода collectors прошли. Отдельно остаётся SQL-приёмка каждого production entrypoint и сборка full poll с одним backend для maintenance lease и всех его транзакций.
Постоянные routing profile ID/version теперь передаются доверенным внутренним контекстом; scoped request v3/checkpoint v2 сохраняют исходные полномочия. Forward fences проверяют их после durable intent, а ручной inverse захватывает их на всю сессию и ограничен исходным validUntil. Проверены actual SQL writer12/CLI3, scoped persistent11/metadata7, базовые 133/8/17/10/40 и настоящий dump/restore/tamper; финальная inverse-fence дельта отдельно прошла 3 поздних изменения с нулём PATCH/HTTP. Существующая CLI SQL-регрессия, полный MCP, IPsec/module-completion, адресные модели, build/lint прошли. Новых маршрутов, production-миграции, включения controller/reserved inverse, деплоя и обращений к CHR нет; счётчик pending прежний. Полный inverse lifecycle после финальной узкой дельты не повторялся. Ниже сохранены предыдущие снимки; их границы уточняет текущий протокол.
Новый протокол runner/routing authority: все шесть диагностик проверены через actual dispatcher/approval/apply/leased runner, с полными страницами и заменой credential на observer read-only. Отмена до execute имеет подтверждённый ноль этапов и rejected/cancelled без needsReview; отмена во время запроса сохраняет unknown/quarantine без повтора. Во временной PostgreSQL прошли 8 runner, 17 persistent-authority, 40 poll-journal и 10 lease-сценариев вместе с базовыми 133 SQL и настоящим dump/restore/tamper. Routing validator ещё требует подключения к controller/checkpoints; новые production-маршруты и схемы poll не активированы.
Для полного server poll подтверждён недостаток row-trigger-only барьера: relation lock уже взят до ожидания advisory lock. В SQL воспроизведён безопасный отказ 55P03 без DROP; early admission до SQL проходит. Аудит охватил 12 partition parents и 17 writer-групп, включая ORM и FK cascade; их общий допуск на том же backend ещё нужно подключить. Snapshot-only сценарий не заменяет полную операцию poll.
SQL journal 0035 дополнен проверенным слоем общих adapters и отмены: 133 реальных SQL-сценария, настоящий dump/restore/tamper и loopback HTTP всех шести REST-диагностик через общий executor с синтетическими provider-ответами. Сохранены REST JWT/local identities, scoped BW fallback и текстовый контракт DNS CNAME/MTU. MCP adapter закрепляет реальный operation/step и private binding; историческое чтение авторизует текущий read credential без замены исходной подписанной identity. Миграция 0036 хранит запросы отмены, runtime передаёт opt-in AbortSignal и отделяет diagnosticProgress от configuration writes. Модельные проверки, полный MCP/IPsec/module-completion, build и scoped ESLint прошли. Полные публичные результаты до 128 KiB подготовлены для выдачи страницами с SHA-256.
/probes/run пока не переключён на этот слой: нужны production-подключение storage admission/quota/retention, production key provisioning, регистрация MCP run/read/cancel и HTTP transport-приёмка зарегистрированных маршрутов. Пользователь разрешил GC; его адаптированный патч и изолированная SQL-приёмка завершены в новом этапе в начале документа. Очистки действующей БД не было. Реестр и pending не изменились; production-схема не применялась.
Новый протокол runtime admission и восстановления: на отдельной PostgreSQL прошли 15 сценариев атомарного admission через applyPlan — операция, 2 mutation units, 2 profile slots и общий source-step slot записываются на одном backend без двойного debit. Повторное применение и lost COMMIT ACK не выдают capability продолжения. Полный manual inverse SQL/HTTP и dump/restore/tamper прошли; исправлена найденная регрессия подписи: отсутствующие optional reserved-поля больше не меняют fingerprint ручной квитанции. Reserved engine использует тот же 0031 PK и общий исполнитель; положительный autoRecovery lifecycle и его запуск остаются закрыты context guard. Отдельная повторная IPsec delete/pool-приёмка также прошла.
Добавлена инертная модель полного сетевого verifier: 46 тестов. Она различает installation table и probe VRF, требует точные route/next-hop/BGP/BFD/probe/log identities, две стабильные полные выборки, полноту log interval и общий бюджет ≤120 секунд между forward/inverse. Любая неопределённость преобладает над failure. Это классификация переданных наблюдений, не native reader, подписанный checkpoint, authority или разрешение на откат; per-response wire/page limits ещё должен обеспечивать native adapter.
Для restore введена общая process-local защёлка: после начала target psql NetFlow/планировщик/RIPE не запускаются до успешных миграций, включая последующий export в том же процессе. Шесть тестов реальных entrypoints с инертным I/O, независимые 15 адресных проверок и настоящий owned terminal restore прошли. Durable startup recovery не реализован. Подготовлен точный манифест 36 SQL-файлов (14 сценариев); dispatcher, независимый schema comparator и control namespace ещё не подключены. Финальные MCP-профиль, модели, backend build и lint прошли; все backend-профили не повторялись. Деплоя, production DDL и обращений к CHR не было.
Ниже сохранены предыдущие этапы; их открытые пункты нужно читать с учётом нового протокола. Общий план остаётся открытым, реестр и 9 pending не изменились.
- IPsec init v3: общий REST/MCP executor всех полей мастера, подпись только новых ACK-owned сертификатов, source/authority fences, полный raw preflight и обязательная история. Изменение существующего IPv4-пула учитывает DHCP, PPP, Hotspot и next-pool; внешние потребители блокируют план.
- IPsec revision restore v1: строгие schema/fingerprint/xmin, точные записанные поля и empty clears, сохранение PSK включая пробелы, проверка PKI/profile/proposal/group/NAT/pool зависимостей и отсутствие replay. Незаданные native-поля существующего mode-config сохраняются. Если старый snapshot не позволяет восстановить отсутствующую policy или mode-config, legacy certificate-поле либо unknown auth capability, операция отказывается до записи; утраченные ключи не генерируются заново. Непустой native default для записанного пустого значения не принимается как успешное восстановление.
- WireGuard revision restore v1: полная форма интерфейсов/peers/IPv4/IPv6, encrypted desired keys, явный inventory удалений, staged disable/enable, private per-command proof/read-back и обязательная история. Ключи в модель не выдаются; сверка использует только точный сохранённый VERIFIED checkpoint.
- IPsec server delete v2: после отдельного разрешения применён шестифайловый патч предохранителей IPv4-пулов. Сценарий удаления не расширен: внешние DHCP/PPP/Hotspot/next-pool потребители запрещают удаление, старые планы v1 не выполняются. Внешняя RADIUS Framed-Pool authority не выводится из native-конфигурации.
- VRF production preparation: явный productionAdmission:true на существующих typed tools сохраняет прежнюю подготовку простых планов без флага. Encrypted ticket сохраняется вместе с реальным планом в одной транзакции; ключ выводится из durable private material с отдельным purpose. Admission/private domains v2 исключают только скалярную telemetry соответствующего каталога; неизвестные и вложенные поля остаются sealed. 86 моделей отказа, 7 runtime SQL-сценариев и 11 SQL-контрактов tickets пройдены. Unknown claim не перезаписывает завершённую операцию.
- VRF transition model: 62 проверки шести lifecycle-фаз и произвольных IPv4 /23, IPv6 /56. Это чистый classifier для доказанных bridge effects; reenable/LL revival требуют непрерывного checkpoint, disable ограничен наблюдавшимся циклом. Production executor и native companion admission не включены.
- Мониторинг частичного результата: bounded nativeProgress отдельно показывает ACK и подтверждённые read-back команды; счётчик завершённых service steps сохранён отдельно. Private error payload не публикуется.
SQL/HTTP использует временный PostgreSQL и локальные RouterOS fixtures. Новый fixture agent переиспользует максимум два соединения только с точным связанным loopback endpoint, сохраняет настоящий HTTP/parser/guards и не повторяет запросы; teardown восстанавливает transport. Это устраняет подтверждённый Windows EADDRINUSE в накопительном тесте. Production HTTP agent не изменён; его нагрузочная и живая CHR-приёмка этим протоколом не заявляются. Сборка, профили MCP/IPsec/WireGuard, новые модели, scoped ESLint и настоящий dump/restore/tamper проверены в указанном отчёте; все 27 backend-профилей не повторялись. Деплоя, live collector или изменений CHR не было.
Остаются 9 REST-сценариев: два экспорта существующих IPsec-сертификатов и семь ручных collectors (server/API ping/probes, traffic, uptime/group/speed-test). Persistent routing authority/reserved inverse/controller, production VRF executor/recovery/forwarding, внешние AI-клиенты, live portal sender/UI и независимая трёхузловая приёмка остаются в полном плане. Доступны только два CHR.
Основы server poll, всех шести server probes и экспорта существующих IPsec-сертификатов пока не зарегистрированы. SQL journal probes отдельно принят на временной БД; подключение полного REST/MCP пути ещё не проверено. Production poll adapter прошёл инертные проверки и требует настоящего журнала и global writer lease. Production export и выдача его файлов выключены; разрешение CREATE клиента не распространяется на существующие ключи или ключ CA. Счётчик pending сохраняется.
Исторические этапы
Прежние счётчики и ограничения ниже относятся к соответствующим снимкам; текущий реестр и протокол приведены выше.
Актуальный итог этого этапа: объединённый протокол, 350 инструментов; 188 mediated / 62 excluded / 12 pending из 262 REST-маршрутов. Полный план остаётся открытым.
NetFlow принят с финальными поправками: netflow.settings.update v3, полный {settings: …} из десяти полей, резерв 4 публикации при двух фазах. SQL подтвердил отказ старого v2 и бюджета 3 до записи. До ACK нет timer/packet/enrichment и автоматического повтора startup; normal runtime после ACK отделён от UDP readiness. IPsec CREATE принят с точным bounded reader: приватный PKCS12 читается по проверенному native ID без поиска нового файла по имени; поток, размер, общее время и допуск ограничены. v1 этих двух отчётов сохраняется как исторический снимок, текущие ограничения и поправки описаны в v2.
Основная MCP SQL/HTTP-регрессия завершилась с кодом 0 вместе с настоящим dump/restore/tamper на baseline до последних двух поправок. Финальные дельты отдельно прошли свежие целевые SQL/HTTP, весь MCP model profile, NetFlow settings/file profiles, backend build и ESLint. Это не повтор всех 27 backend-профилей и не живая CHR/UDP-приёмка. VRF reader/admission/tickets прошли 76 моделей и 11 SQL-сценариев; native execution пока выключен. Деплоя и новых обращений к CHR не было.
Текущий подтверждённый срез: 350 инструментов; 188 mediated / 62 excluded / 12 pending из 262 REST-маршрутов. Полный план открыт. Ниже сохранены исторические этапы; их прежние счётчики и ограничения относятся к указанным снимкам.
- Полные настройки NetFlow и ключи: общий REST/MCP executor всех десяти полей, включая no-op/display-only restart; full-config CAS, постоянные phase intents и внутренние main/worker lifecycle checkpoints. Старый handler из четырёх полей заменён общим executor; актуальная версия v3 и бюджет 4 описаны выше (промежуточный v2 исторический).
mm_netflow_host_keys_generate_planсоздаёт только неполную пару и выдаёт публичный ключ. SQL/HTTP проверяет настоящий disabled main flush; worker startup/shutdown проверены инертными моделями. Живой UDP worker отдельно не принимался. - CREATE клиента IPsec: PSK/certificate/static IP, полный private proof и dependency closure, подпись/export/cleanup без повторов, обязательная история. После отдельного разрешения пользователя PKCS12 выдаётся владельцу с network-write через зашифрованный портал на 15 минут только при
privateKeyExport=trueи human approval; модель получает квитанцию. Loopback SQL/HTTP всех веток и owner download прошли; настоящие CHR/SA/forwarding не проверялись. - Production VRF raw reader и durable tickets: 17 raw-каталогов и конкретные parent/peer/VTEP зависимости, HMAC admission, реальные encrypted plan bindings, отдельное соединение для одноразового claim. 76 моделей отказа и 11 SQL-сценариев прошли. Это precondition, native execution не включён; runtime journal/key provisioning и production transition classifier остаются открытыми.
Целевые SQL-приёмки, настоящий dump/restore/tamper, весь MCP model profile, IPsec/settings/purge/ownership profiles, backend build и адресный ESLint прошли. Основная SQL-регрессия baseline затем завершилась; финальные дельты и точные границы проверки приведены в объединённом протоколе выше. Все 27 backend-профилей повторно не заявляются. Деплоя, запуска живого collector и обращений к CHR в этом этапе не было.
Оставшиеся REST-сценарии: IPsec certificate export, user certificate export, server init и revision restore; ручные servers/API-ping/probes/traffic/uptime/speed-test collectors; WireGuard revision restore. Persistent routing profile authority/reserved inverse/controller, production VRF native/forwarding, внешние AI-клиенты/portal sender/live UI и независимая трёхузловая приёмка остаются в исходном объёме; доступны два CHR.
Удаление IPsec-сервера принято: mm_ipsec_server_remove_plan использует общий REST/MCP executor с полным ordered manifest, защитами foreign references и объявленными CA cascade. Profiles/proposals и чужие объекты сохраняются; каждый DELETE проходит private stage proof, read-back и checkpoint, затем обязательную историю. Proof v2 исключает только certificate expires-after; даты, trust, CRL, ссылки и неизвестные поля сохранены. Старые планы блокируются повышенными версиями действий. SQL/HTTP, весь IPsec-профиль, весь MCP model profile, build, lint и настоящий dump/restore/tamper прошли. Реестр: 348 инструментов; 185 mediated / 62 excluded / 15 pending из 262 REST-маршрутов. Настоящий CHR cascade/forwarding остаётся отдельной приёмкой; полный план открыт.
mm_ipsec_server_remove_plan принимает {serverId,removeCertificates}; removeCertificates по умолчанию true, как в REST. Всегда нужны network-write, server/operation scope и подтверждение человеком. План показывает native-команды, все затрагиваемые объекты и косвенные удаления CA; budget включает каждый такой сертификат и историю. false сохраняет сертификаты. Пустой manifest записывает только историю. Старый REST DELETE /api/ipsec/server/:serverId?removeCertificates=false сохраняет {ok:true}; неподтверждённая история или команда возвращает ошибку без предложения повторить удаление.
Параллельно подготовлены основы модулей NetFlow settings и production VRF: 43 чистые модели executor и 65 моделей отказа admission соответственно. NetFlow ещё требует CAS/intents и внутренних collector fences; VRF — raw reader, durable ticket store, transition classifier и native executor. Runtime этих компонентов не подключён; это не закрывает ожидающие REST/VRF-сценарии.
Полный PATCH клиента IPsec принят: mm_ipsec_user_edit_plan использует общий REST/MCP executor для имени, static IPv4/возврата к пулу, PSK, Remote ID и disabled, включая cert-only promotion/ignored fields, shared/foreign mode-config и историю. PSK в MCP передаётся только через привязанную к владельцу/серверу/клиенту ссылку. Каждый ACK проверяет точную сохранность полного private state; отзыв PSK-reference после первого ACK блокирует следующую команду. Исправлена ветка пустого staticIp: 400 до изменения имени. SQL/HTTP parity, весь IPsec-профиль, весь MCP model profile, build, lint и настоящий dump/restore/tamper прошли. Реестр: 347 инструментов; 184 mediated / 62 excluded / 16 pending из 262 REST-маршрутов. Живые CHR и forwarding этим прогоном не проверялись; полный план остаётся открытым.
mm_ipsec_user_edit_plan принимает {serverId,clientId,patch}. Используйте ID клиента из каталога (identity:*ID или cert:*ID). Поля patch: name, staticIp (IPv4 или null для пула), remoteId, disabled, pskSecretRef; пустой patch записывает только историю. Ссылка PSK создаётся владельцем в портале MCP с purpose ipsec-user-psk:<serverId>:<clientId> для этого сервера. Сырой psk через MCP отклоняется. Сертификатный клиент без identity сохраняет прежнее поведение ignored fields, показанное в предупреждении плана. Общие mode-config и их потребители входят в зависимости плана. Автоматического обратного действия и повтора неизвестной команды нет.
Native IPsec dependency guards приняты: mm_ipsec_peer_create_plan v4 закрепляет точный/default profile и существующие ссылки; mm_certificate_update_plan v3 учитывает цепочку сертификатов, identities и peers и требует одновременно network-write и certificates-write. Оба входа требуют human approval и полного private proof вместо усечённого generic snapshot. Смена подключения блокируется до первого GET, старые прямые native/inverse шаги — до SQL и native access. SQL/HTTP, прежние IPsec DELETE/PATCH, настоящий dump/restore/tamper, весь MCP model profile, build и lint прошли. Ожидаемый rename ссылок проверен на loopback; настоящий CHR rename остаётся открытой приёмкой. Реестр без изменений: 346 инструментов; 183 mediated / 62 excluded / 17 pending.
REST/MCP rebuild NetFlow принят: mm_netflow_facts_rebuild_plan требует human approval и полного global/server scope; mm_netflow_facts_rebuild_reconcile сверяет историческую квитанцию без повтора записи. На временном PostgreSQL прошли actual main-writer drain, атомарные факты/событие/квитанция, scope/protection guards, новый credential и JWT REST parity. Backend build, весь MCP model profile и scoped lint прошли. Реестр: 346 инструментов; 183 mediated / 62 excluded / 17 pending из 262 REST-маршрутов. Живой worker отдельно не запускался, деплоя не было; полный план остаётся открытым.
mm_netflow_facts_rebuild_plan принимает строго {}. Право — mm:traffic:write; необходимы global scope и все серверы текущего каталога. Даже autonomous mode требует подтверждения человеком. Модель получает только {ok,buckets,facts,days,jobId}; private source/classifier proofs и зашифрованная привязка скрыты. mm_netflow_facts_rebuild_reconcile принимает {operationId} исходной операции того же подключения и требует актуального допуска к обеим операциям и всем исходным серверам. Отсутствие квитанции не разрешает повтор. Старый REST POST /api/traffic/flow/rebuild-facts возвращает прежние четыре поля без jobId; поздняя потеря допуска после публикации даёт unknown, а не предложение повторить запрос.
Flow engine wiring принят: после отдельного разрешения применён цельный патч engine/worker/purge. Backend build, native-conservation SQL/HTTP, весь traffic-flow профиль, SQL logs и настоящий dump/restore/tamper прошли. Общий rebuild проверен на настоящих partitioned таблицах с явной no-op drain-фикстурой: дневная агрегация, rollback обоих кубов, поздние защиты/отзыв и чтение известной квитанции до drain. REST/MCP принят следующим этапом выше; проверка живого существующего worker остаётся открытой; деплоя и запуска collectors не было.
Native VRF v5 принят: отдельный новый fixture подтвердил create/rename/disable/re-enable/member transfer/delete, 18 ACK с read-back и штатную очистку. Независимый GET без исключений подтвердил ноль тестовых объектов и все 34 исходных хеша 17 каталогов; SSH закрыт. Base-контракт содержит 218 моделей отказа. Generic production MCP companion admission и forwarding этим прогоном не проверены и остаются открытыми.
Отдельный SQL-контракт flow writer прошёл на временном PostgreSQL: атомарность двух shadow-кубов, события и квитанции, отсутствие повторного тела, lost COMMIT ACK, реальный advisory-lock barrier и отказ по отзыву до COMMIT. Это отдельный writer-контракт; последующая REST/MCP-приёмка приведена выше. npm --prefix backend run test:mcp:vrf-cleanup теперь запускает все три cleanup-контракта (50 + 53 + 94 модели отказа); весь профиль прошёл.
OSPF listing order принят: snapshots v3, optimizer v9 и template C/U/D v5/v4/v3 прошли main MCP SQL/HTTP, OSPF-профиль, SQL logs, настоящий dump/restore/tamper и весь MCP model profile. Порядок строк сохраняется; drift до PATCH отклоняется, после ACK остаётся unknown без VERIFIED. Общий flow rebuild executor ещё в работе. Native VRF v4 подтвердил create/rename/disable/re-enable, но остановился после ACK transfer на переназначении собственных kernel route IDs и отсутствии одного LL/LL-route. Отдельная очистка завершена: все семь созданных объектов удалены с ACK и read-back, без повторов команд; независимая заключительная GET-проверка подтвердила ноль тестовых объектов и все 34 исходных хеша без исключений. Прогон v4 не подтвердил полный lifecycle; production MCP companion admission остаётся открытым.
Предыдущая зафиксированная дельта: снимок 383 файлов прошёл native-conservation SQL/HTTP, профиль traffic-flow, SQL logs, настоящий dump/restore/tamper, весь MCP model profile и backend build. Instance-based fact accumulator выделен без изменения REST/rebuild; атомарный MCP rebuild остаётся в работе. Native VRF v3 подтвердил create/rename, но остановился после ACK disable: RouterOS удалил dynamic table, сохранил выключенный virtual interface и вернул адреса/маршруты в main. Re-enable/transfer не запускались. Отдельная очистка завершена: все семь ACK-owned объектов удалены без повторов команд, независимая GET-проверка подтвердила исходные 34 хеша и отсутствие тестовых объектов. Полный lifecycle не принят, остановленные команды не повторяются.
Этап в работе: общий native verifier проверяет назначенный CREATE ID, состав и неизменность соседних объектов в видимой проекции; сохранён порядок 11 каталогов. Source-bound snapshots v2 и expected-prefix checks защищают подготовку, каждый шаг и dispatch после durable native intent. Целевая SQL/HTTP-приёмка, 54 HTTP-модели, ECMP+hash/singleton inverse и dump/restore прошли. OSPF builder исправлен со свежим source-bound capture (v8); SQL/HTTP подтвердил полный owner graph и VRF context, измерив 93 HTTP-запроса на один PATCH. Web CREATE adapter исправлен: CREATE не передаёт id даже как undefined, строгая схема сохранена. Повторная объединённая SQL-регрессия снимка 379 файлов завершилась с кодом 0: main integration, профиль OSPF, SQL logs, настоящий pg_dump/restore и tamper refusal. Весь MCP model profile и backend build также прошли. Все 27 backend-профилей этой дельты не повторялись.
-
Вложенный polling OSPF устранён: статический аудит вывел 1232 GET на один cost PATCH в трёхузловой HTTP-фикстуре из-за вложенного полного graph guard. Это не native timing measurement. Исправление внесено: grant/source перед каждым чтением сохранены; полный граф проверяется на пяти границах, последним перед dispatch и после ACK до VERIFIED. Модели source ABA/revocation и post-ACK classification прошли; успешная объединённая SQL-регрессия подтвердила 80 GET + 12 read-only POST + 1 PATCH = 93 HTTP-запроса вместо 1232 GET. Это трёхузловая HTTP-фикстура, не native forwarding-приёмка.
-
Общий этап пока не принят: VRF требует typed companion-контрактов для автоматически перемещаемых/удаляемых connected routes, таблиц и virtual interfaces. Native-v2 на RouterOS 7.24.5 подтвердил создание двух bridge, четырёх адресов и VRF, затем остановился на неизвестных kernel companions; rename/toggle/transfer не выполнялись. Отдельная очистка завершена: все семь ACK-owned объектов удалены без повторов команд и без прямого удаления kernel-объектов. Первый cleanup остановился после ACK IPv4 DELETE из-за изменения собственного bridge status; GET-диагностика и отдельный guard точного наблюдённого перехода позволили проверить отсутствие удалённых ID и удалить оставшиеся три объекта. Независимая заключительная GET-проверка подтвердила ноль тестовых объектов и совпадение всех 34 исходных хешей 17 каталогов уже без исключений. Исходный unknownWrite latch и отчёт не изменены. Полный native lifecycle и generic MCP companion admission остаются открытыми.
Предыдущая принятая дельта: устранена подмена ID в native CREATE. Все 30 CREATE-схем запрещают id; старые некорректные шаги блокируются до отправки, проверка использует только acknowledged .id, inverse выбирает единственную добавленную строку. CREATE-версии повышены, recovery — v4. SQL/HTTP-протокол: код 0, нормальный create/inverse сохраняет существующий объект, legacy poison и старые версии блокируются, ignored/lost не повторяются. Весь профиль MCP, build и ESLint прошли; целевая recovery/maintenance SQL-регрессия на v4, включая primary-down alternate, и настоящий dump/restore/tamper завершились с кодом 0. Независимое read-only review не нашло ошибок в этой дельте. Полные 27 профилей после этой дельты не повторялись; принятый предыдущий прогон указан ниже. Реестр остаётся 344 инструмента; 182 mediated / 62 excluded / 18 pending.
- Усилить общий verifier: новый assigned ID должен отсутствовать before, изменения должны сохранять соседние объекты и порядок правил. Добавить expected-prefix proof между шагами и полные private/source/dependency contracts. Эта дельта не доказывает whole-catalog conservation. Статический аудит до исправления ID.
Предыдущий этап, реестр: 344 инструмента; 182 mediated / 62 excluded / 18 pending из 262 REST-маршрутов. SLA и два IPsec-адаптера прошли целевую SQL/HTTP-приёмку с кодом 0 и настоящим dump/restore/tamper. Первый полный прогон остановился на дубликате разрешения в ACME-фикстуре (код 1); дубликаты исправлены только в двух тестовых фикстурах. Повторная полная регрессия нового снимка 360 файлов завершилась с кодом 0: все 27 backend-профилей, SQL /logs, настоящий dump/restore/tamper прошли. UI не менялся, реальные CHR в этой серии не менялись; весь план остаётся открытым.
mm_route_optimizer_plan v6 требует свежие SLA и preflight перед PATCH, включая fence после durable intent. После записи устаревший или плохой SLA не мешает сохранить точное CONFIG_APPLIED; контрольная проба проверяется отдельно. Это подтверждение конфигурации и контрольной пробы, а не пересылки трафика или нового SLA. Rights/policy/source/protection и immutable preflight identity остаются обязательными после записи. Ручной recovery v3 повторно проверен; автоматический scoped controller/reserved recovery остаются выключенными.
mm_ipsec_certificate_remove_plan (network.ipsec.certificates.delete) принимает serverId, name, force=false. Он удаляет один выбранный native сертификат, включая foreign; force разрешает разрыв peer/identity references, но не CA cascade или CRL bypass. mm_ipsec_peer_edit_plan (network.ipsec.peers.update) принимает serverId, peerId и patch: name/address/exchangeMode/passive/profile/disabled, а также comment для business MCP/native. REST сохраняет прежнюю схему без comment. Пустые строки передаются, same-value отправляет PATCH, пустой patch сохраняет только историю. Certificate presence запрещена. Native rename/reference projection пока проверена только на loopback, её несовпадение даёт partial без повтора.
Native mm_certificate_delete_plan, mm_ipsec_peer_delete_plan, mm_ipsec_peer_update_plan v2 используют те же guards и требуют отдельного business operation scope. Для native certificate DELETE нужны одновременно certificates-write и network-write. Все новые сценарии требуют human approval, exact private source/read-back, managed-only history и generic VERIFIED. Потеря ответа не разрешает replay. Известные секреты, отражённые в названиях зависимостей, маскируются.
Предыдущий этап: 342 инструмента; 180 mediated / 62 excluded / 20 pending из 262 REST-маршрутов. Разрешённый пользователем WireGuard export подключён: целевая SQL/HTTP-приёмка и полная регрессия объединённого снимка завершились с кодом 0, включая 27 backend-профилей, SQL logs и настоящий dump/restore/tamper. Последующие коррекции REST validation/native duration приняты отдельной целевой SQL/HTTP-проверкой; полный прогон после этой дельты не повторялся. Полный план остаётся открытым.
mm_wireguard_export_plan (network.wireguard.export) принимает serverId, interfaceName, format (rsc, conf, peer-conf), необязательный peerId (native или serverId:*ID) и includePrivateKey (по умолчанию false). Нужны server/operation scope и mm:network:write; портал также требует обычный доступ к разделу MCP (mm:mcp:admin или mm:settings:admin). Даже autonomous mode требует человеческого подтверждения. Модель получает только квитанцию. Зашифрованный файл доступен 15 минут через существующую кнопку «Скачать файл» в операции MCP только вошедшему владельцу с действующими правами, source/policy/protection proofs и exact VERIFIED checkpoint. Отзыв доступа во время чтения блокирует выдачу; HTTP использует private/no-store. Настоящие ключи в этой приёмке не использовались.
REST /api/wireguard/export использует тот же reader/renderer и сохраняет JSON {format, filename, content}. Только явный includePrivateKey=true включает ключ интерфейса в rsc/conf; peer-conf не включает приватные ключи. Имена файлов нормализуются в безопасный набор символов. PSK и невоспроизводимые состояния возвращают явную ошибку: несколько/динамические/специальные адреса, disabled peers/interface в conf, неоднозначные и неполные native-каталоги. Экспорт не подтверждает готовность туннеля или маршрутизации.
Предыдущий этап recovery/maintenance: целевая SQL/HTTP-приёмка завершена с кодом 0, включая настоящий dump/restore/tamper; его проверки прошли и в объединённой полной регрессии export. Реестр: 341 инструмент; 179 mediated / 62 excluded / 21 pending из 262 REST-маршрутов. Протокол. mm_route_optimizer_plan v5 заранее закрепляет отдельный management transport, а mm_operation_recovery_plan v3 поддерживает ручной обратный план для exact scoped Community operation. Обратное действие требует человеческого подтверждения, подписанного CONFIG_APPLIED исходного переключения и свежей проверки исходного кандидата уже в изменённом контексте. Один исходный operation/step может занять только один durable inverse intent. Срок — не более 120 секунд от исходной операции с дополнительными ограничениями credentials, policy и канала; неизвестный исходный результат не разрешает inverse. Новые native ID, тела правил или credentials из ответа модели не принимаются. После read-back сохраняется RECOVERY_CONFIG_APPLIED, после контрольной пробы — RECOVERY_VERIFIED; read-only reconcile отдельно проверяет exact generic VERIFIED. Автоматический recovery и scoped controller остаются выключенными.
Резервный transport закрепляется, пока primary доступен. При последующем отказе primary сверяется только его логическая SQL-идентичность и версия подключения, а сетевые чтения и обратный PATCH идут через закреплённый адрес с проверенной RouterOS license identity. Замена, отзыв, expiry канала или изменение подключения запрещают этот transport. Независимость физического пути остаётся человеческой аттестацией; loopback-приёмка не доказывает независимость реальных CHR.
Локально принят также mm_ipsec_user_remove_plan (network.ipsec.users.delete): serverId, namespaced clientId вида identity:*ID или cert:*ID, removeCertificate по умолчанию true. Он сохраняет REST-семантику удаления клиента и необязательного безопасного удаления его сертификата/mode-config; CA, серверные сертификаты и общие зависимости не удаляются. Отдельные команды и история проверяются последовательно, unknown не повторяется.
mm_netflow_purge_plan (traffic.flow.purge) требует полного global/server scope, traffic-write и человеческого подтверждения. План явно показывает необратимую очистку всех шести NetFlow-таблиц, остановку с подтверждением завершения worker, сохранение настроек/ключей/peers, штатный restart и общий retention maintenance. Последний может удалить показанные истёкшие разделы traffic, ping, uptime, snapshots и internet-path: каждый включён в объекты и бюджет плана, новый неутверждённый раздел не удаляется. Потерянный COMMIT не повторяется; новые flows после restart допустимы. Отправка уведомлений этим сценарием не запускается.
На предыдущем этапе локально приняты Route AI checkpoint и два адаптера, с отдельным focused-протоколом. Реестр — 339 инструментов; 177 mediated / 62 excluded / 23 pending из 262 REST-маршрутов. Полная последовательная регрессия завершилась с кодом 0: все 27 backend-профилей, SQL /logs, настоящий dump/restore/tamper. Focused SQL/HTTP, targeted models, build и ESLint также прошли. Scoped controller и автоматический inverse ещё не включены.
mm_server_test_connection_plan / servers.test-connection проверяет новое назначение до сохранения сервера через два bounded GET. Все параметры REST, включая hostname, API path и TLS, поддержаны; DNS ограничен и адрес закрепляется с исходным Host/SNI. Нужны mm:servers:write, global/full-server scope и человеческое подтверждение. Вместо raw password передайте owner secret passwordRef без serverId, с purpose server-connection-test:<SHA256 нормализованных host/port/useSsl/verifySsl/apiPath/username>; точное нормализованное значение строит serverConnectionSecretPurpose. Результат скрывает отражённый пароль. Unknown transport/parse/overflow не повторяется, reconcile не отправляет новые запросы.
mm_ipsec_peer_remove_plan / network.ipsec.peers.delete принимает serverId, точный peerId и force (по умолчанию false). Force разрешает разрыв ссылок identities, сами identities сохраняются. Shared REST/MCP executor проверяет bounded полный private proof, сохраняет один DELETE и managed-only историю. Совпадение конфигурации после lost acknowledgement показывается отдельно: matchesDesiredState требует exact generic VERIFIED receipt и подтверждённую историю. После partial/unknown нет повтора или автоматического inverse.
На предыдущем этапе mm_route_optimizer_plan имел версию 4, mm_route_profile_save_plan — 3. Старые планы требуют новой подготовки. Scoped PATCH теперь сохраняет encrypted CONFIG_APPLIED до post-probe и отдельно подписывает результат пробы; generic VERIFIED без обоих подтверждений недостаточен. Подтверждённый отказ пробы — partial, неизвестная проба — unknown. Profile CAS/per-profile lease защищают состояние от stale tick, но profile-version у native transport и scoped recovery engine ещё не реализованы. Scoped auto/controller guards сохранены; forwarding этими проверками не подтверждён.
Регистрация защиты RouterOS-объекта с ID вида *3 требует serverId: без него POST /api/mcp/protections возвращает 400 INVALID_INPUT до сохранения. ID локален для устройства; одинаковые ID на разных серверах независимы. Legacy-записи продолжают читаться. Протокол подтверждает HTTP-валидацию и остановку REST/MCP import при поздней scoped-защите peer до первого PATCH, без автоматического повтора. Focused SQL/HTTP, настоящий dump/restore/tamper, build, JWT administration model и ESLint прошли; полные 27 профилей повторно на этой правке не запускались.
Этап 24 октября — общий WireGuard import и scalar proofs — локально принят: протокол и отпечатки исходников. Реестр: 337 инструментов; 175 mediated / 62 excluded / 25 pending из 262 REST-маршрутов. Focused SQL/REST/MCP и полная последовательная регрессия завершились с кодом 0: 27 backend-профилей, SQL /logs, настоящий dump/restore/tamper, build и ESLint прошли. UI не менялся; прежние результаты 16 браузерных сценариев, двух helper-тестов и frontend TypeScript унаследованы после сверки hashes исходников и логов. Новый live import/browser не заявляется. Полный план остаётся открытым.
Для импорта владелец с правом mm:mcp:admin (или mm:settings:admin) создаёт защищённую ссылку через JWT API POST /api/mcp/secrets: purpose wireguard-import-config, нужный serverId и содержимое .rsc/.conf в value. Полученный secretRef передаётся инструментам как contentRef; исходный файл и ключи модели не передаются. mm_wireguard_import_preview проверяет формат без RouterOS polling (nativeChecked: false). mm_wireguard_import_plan после человеческого подтверждения проверяет актуальное устройство и применяет все объекты по стадиям. Обоим инструментам нужны явно выданные operation IDs, server scope и mm:network:write. Пределы — 256 КиБ, 100 peers, 100 allowed routes на peer.
Все объекты сначала создаются отключёнными, затем отдельно включаются запрошенные peers/address/interface. REST и MCP используют один исполнитель. Preview скрывает ключи, а REST сохраняет совместимую форму с [KEY]. Partial/unknown не разрешают автоматический повтор или очистку. Сверка отдельно показывает совпадение конфигурации; успех требует точного generic VERIFIED checkpoint. Copy revision не подменяет подтверждение native-результата. Handshake, маршрутизация и пользовательский трафик импортом не проверяются.
Basic PATCH/alias/reconcile прошли на двух CHR с удалением всех собственных отключённых fixtures и восстановлением baseline. Native ID equivalence подтверждена на этих fixtures; native multi-peer import/activation и окончательная сетевая приёмка открыты. Update tools имеют версию 3/proofRevision 2, business create — 3/native create — 2: прежние незапущенные планы нужно подготовить заново. Guards принимают только подтверждённую public identity эквивалентных X25519 scalar representations; raw ключи и команды не переписываются.
На том этапе secure export оставался неподключённым. После явного разрешения пользователя он подключён и принят в текущей целевой SQL/HTTP-проверке, описанной в начале документа. Ручные collectors по-прежнему ожидают разрешения глобальных уведомлений. Третий CHR для независимой Home → JumpHost → ExitNode цепочки отсутствует.
Предыдущий этап 24 октября — WireGuard PATCH, пакет событий и совместимость Route AI — локально принят: протокол и отпечатки исходников. Повторная полная последовательная регрессия завершилась с кодом 0: все 27 backend-профилей, SQL /logs, настоящий dump/restore/tamper, MCP-модели, build и ESLint прошли. UI не менялся; результаты предыдущих 16 браузерных сценариев, двух helper-тестов и frontend TypeScript унаследованы после сверки hashes исходников и логов. Реестр: 335 инструментов; 174 mediated / 62 excluded / 26 pending из 262 REST-маршрутов. Полный план остаётся открытым.
mm_wireguard_interface_edit_plan меняет поля интерфейса и основной адрес через общий REST/MCP сервис. Закрытый ключ передаётся моделью только как owner/purpose/server secret reference. Поддерживаются rename внутренних peer/address ссылок, вторичные адреса сохраняются. Внешние routing/firewall/application зависимости требуют отдельного плана. Native alias и общий interface editor вызывают тот же сервис; их версия — 2. Native PATCH/readiness ещё не приняты: на двух доступных CHR текущие WireGuard-каталоги пусты.
mm_events_batch_append_plan добавляет до 200 записей клиентского журнала после человеческого подтверждения. Поля REST сохраняются; нормализованный JSON ограничен 64 КиБ/12 уровнями. Содержимое пакета остаётся в зашифрованном плане, UUID генерируются сервером, INSERT атомарен. Эти записи не являются доказательствами выполнения указанных в eventType/sourceModule действий.
Для глобальной read-only сверки отдельно выдайте operations.global.reconcile / mm_global_operation_reconcile вместе с исходным действием и full global/server scope. В портале прежняя кнопка сверки сама выбирает глобальный обработчик. Совпадение состояния без точного VERIFIED checkpoint не подтверждает выполнение неизвестной операции; повторной записи нет.
Route AI возвращает candidateDiagnostics: недоступный резерв не делает неизвестным здоровый выбранный путь. У отключённых BGP peers сохраняются private proofs и проверки dormant input/output references. Ошибки авторизации/JSON, смена источника, отмена и лимиты прерывают весь контекст. Положительная версия старого BGP включает только legacy-read-only с instance: null; запись и native pre-7.20 приёмка открыты. Контракт версий описан в документации MikroTik.
Ручные collector MCP-операции пока не выданы: их существующий глобальный hook может обработать и отправить ожидающие Telegram-уведомления. Добавление guarded scheduler runner отклонено автоматической проверкой до отдельного разрешения пользователя; patch не применён. Общая REST-логика и опциональные access guards подготовлены и проверены только локальными имитациями. Никаких реальных уведомлений в этом этапе не отправлялось.
Предыдущий этап 24 октября — scoped Community и терминальная диагностика — локально принят: исторический протокол и отпечатки исходников. Исторический реестр: 332 инструмента; 172 mediated / 62 excluded / 28 pending из 262 REST-маршрутов. Focused SQL/HTTP и полная последовательная регрессия всех 27 backend-профилей, SQL /logs, настоящий dump/restore/tamper, все 16 браузерных fixture-сценариев, два frontend helper-теста, модели, build, TypeScript, ESLint и diff check прошли.
В MCP → Route AI → Контрольная проверка пути выберите назначение: Путь Community учитывает BGP/owned rule и может служить допуском к отдельному плану переключения; Самостоятельный контрольный путь проверяет probe VRF, интерфейсы, адреса и hops без BGP. Второй результат не допускает переключение Community. В mm_route_path_verify v2 параметр proofPurpose равен community по умолчанию или control-path. Старые подтверждения без purpose требуется получить заново. Обратный путь и весь пользовательский трафик этой пробой не подтверждаются.
mm_route_optimizer_plan v3 поддерживает ручной human-approved scoped Community план: явный BGP context, точная native identity, один PATCH только поля rule, свежие SLA/Community path proofs, source/protection fences и точный VERIFIED checkpoint для read-only reconcile. Скрипты, comments и seals остаются приватными. Scoped controller и автоматическое восстановление пока недоступны; UI блокирует такую активацию и позволяет сохранить отключённый профиль.
mm_server_terminal_diagnostic / servers.terminal.read принимает serverId, типизированный diagnostic и параметры выбранного сценария. Это тот же allowlist, parser и форматирование, что REST-терминал: help, адреса, интерфейсы, resource/identity, маршруты/firewall, BGP/OSPF/BFD, логи и ping. Сохраняется право mm:servers:write; планы не создаются. Help обходится без credentials/native I/O. Ping явно помечен как отправка контрольных пакетов; произвольные CLI-команды не принимаются.
Предыдущий этап 24 октября локально принят: исторический протокол и отпечатки исходников. Исторический реестр: 331 инструмент; 171 mediated / 62 excluded / 29 pending из 262 REST-маршрутов. Focused SQL/HTTP и полная регрессия всех 27 backend-профилей, SQL /logs, настоящий dump/restore/tamper и 14 браузерных fixture-сценариев прошли.
mm_acme_settings_update_plan/certificates.acme.update: общая с REST форма directory/zone и owner/purpose secret reference для Cloudflare; retain/replace/clear, human approval, private source/CAS и read-back. Сырой токен модели не выдаётся.mm_wireguard_peer_add_plan/network.wireguard.peers.create: полная форма peer, допустимые зависимости существующего родителя, private key reference или режим auto/none, staged disabled и отдельное включение. Старый native aliasmm_wireguard_peer_create_planвызывает тот же защищённый сервис.mm_database_backup_plan/database.backup: обязательное человеческое подтверждение, полный глобальный scope, общий с REST export/event и исключительный доступ на время экспорта. Для MCP — 64 МиБ/120 секунд, временный закрытый libpq service file и отказ неподдержанных URI до approval. Модель получает квитанцию; зашифрованный dump доступен 15 минут только JWT владельца с settings admin. Существующий REST export сохраняет прежний контракт размера/времени.
Route AI отдельно хранит installation table, probe VRF и BGP connection/instance/input chain/transport VRF. Подпись Community path-check связана с источником, зависимостями и owned target rule. Public review показывает до/после community/gateway/action и число строк снимков. Main-переключение сохраняет исходный owned comment. Совместимость старой формы BGP, scoped controller и автоматическое восстановление ещё требуют реализации/приёмки; autoRecovery явно блокируется. Трёхузловая независимая traffic-проверка открыта: пользователь подтвердил только два CHR. Новых native-команд CHR на текущем этапе нет.
Предыдущая приёмка 24 октября — MCP UI и оба CHR: исторический итог проверки. Срез реестра того этапа: 328 инструментов; 168 mediated / 62 excluded / 32 pending из 262 REST-маршрутов.
В разделе MCP → Планы и операции → Выполнение операций откройте завершённую операцию backups.download и нажмите Скачать файл. Квитанция доступна только актуальному владельцу с правом управления backup. Срок пакета — 15 минут; при изменении источника, истечении срока или отзыве доступа потребуется новый подтверждённый план. Модель получает квитанцию, человек скачивает файл по JWT портала.
Список операций проверяет только подписанные метаданные и текущие права; содержимое backup/S3 и ciphertext не читаются. UI строит URL из UUID, запрещает redirects и освобождает временный Blob URL. Проверены чужой admin, отсутствие backup permission/JWT, unverified/unknown и подменённые шаги, expiry, protection и pause/ABA. Пройдены 11 браузерных сценариев на API fixtures, SQL/HTTP и настоящий dump/restore/tamper, все 27 backend-профилей, SQL /logs, build, TypeScript и ESLint.
Отдельный конфигурационный GRE прогон на двух CHR принят: 24 команды, create/no-op/expand/restore/empty и readonly reconcile, все 16 исходных native fingerprints и оба полных private dependency proofs восстановлены, marker-объектов нет, SSH закрыт. Передача трафика, IPv6 readiness и IPsec SA этим не проверялись. Исторические прерванные попытки сохранены отдельно.
В историческом срезе оставались 32 REST-адаптера и полный non-main/VRF контекст. Текущий принятый контекст и 29 оставшихся адаптеров описаны выше; scoped executor, reconcile/recovery, независимый прямой/обратный трафик и live portal/client gates по-прежнему открыты.
Предыдущий принятый этап 24 октября: пять общих REST/MCP-сценариев и приёмка. Реестр — 328 инструментов; 168 mediated / 62 excluded / 32 pending из 262 REST-маршрутов. Протокол содержит source hashes, focused SQL/HTTP, полный backend-прогон и границы сетевой приёмки. Полный план остаётся открытым.
mm_acme_settings_test_plan/certificates.acme.test: один GET фиксированного Cloudflare endpoint с сохранённым токеном после человеческого подтверждения. Модель не передаёт plaintext токена. Общий REST/MCP-сервис ограничивает время/размер и скрывает provider body; результат подтверждает доступ к API, а не выпуск сертификата/DNS.mm_geoip_update_plan/geoip.update: тот же forced collector Country/ASN, что REST; глобальный полный scope и human approval, ETag/304 и частичный результат. Перед сетевыми и файловыми стадиями проверяются каталог, bounded SHA-256 файлов, ETag и run metadata. Свой ожидаемый proof продвигается только после собственного подтверждённого изменения. Исходный файл сохраняется до атомарнойrename(tmp,target); неизвестная попытка не повторяется.mm_netflow_overlay_apply_plan/traffic.flow.overlay.apply: обе REST-формы/api/traffic/flow-overlayи/api/traffic/flow/overlayиспользуют общий staged executor. Он настраивает WireGuard/IPFIX, необязательный GRE FastPath, адреса/маршрут/firewall, host peer/settings и collector/listener. Нужны полный глобальный scope, traffic/network write, settings admin и человек. HMAC заменяет raw keys в источниках плана; каждый native шаг проверяется. Manual host installation, подтверждённый Linux-agent apply и неизвестный host ответ различаются. Reconcile принимает desired только по точному проверенному private intent/receipt/full afterProof, а не по совпавшему графу с чужими сгенерированными ключами.mm_backup_download_plan/backups.download: человеческое подтверждение обязательно даже в autonomous policy. Общий с REST reader сохраняет remote-first/local fallback, ограничен 8 МиБ/45 секундами. Модель получает квитанцию и ссылку, backup body остаётся в зашифрованном подписанном пакете владельца на 15 минут. Перед чтением/расшифрованием/выдачей проверяются актуальные JWT/owner/credential/policy/generation, источник, выбранное происхождение S3/local, server ownership и xmin epochs. Модельный токен не открывает человеческий маршрут.mm_wireguard_interface_create_plan/network.wireguard.interfaces.create: общий с REST create сохраняет optional IPv4/IPv6, все peer/client поля и допустимые Unicode/quoted имена. Ключи модели — только owner/purpose/server references. Создание и адрес/peer готовятся disabled; включение идёт после проверки подготовленных объектов. Полный source/protection proof проверяется также после durable native intent. Сверка нового сгенерированного ключа требует сохранённого конечного checkpoint; partial/unknown не усыновляются по одному совпадению полей.
Приёмка этих сценариев использовала только локальные HTTP/S3, fake Linux-agent named pipe, ephemeral UDP и временную SQL-БД; реальный Cloudflare, зеркало GeoIP и backup destination не вызывались. Полная браузерная приёмка остаётся отдельным gate.
Отдельный GRE CHR-прогон f1147896: CHR 1 прошёл create/no-op/expand/restore/empty и исходный dependency proof; CHR 2 прошёл первые стадии, но завершение empty остановилось на 401, очистка встретила 500. Всего 22 native-команды; неизвестный план не повторялся. Отдельная очистка по новым marker-bound планам завершилась с кодом 0: все 16 исходных native fingerprints совпали, тестовые объекты удалены, SSH закрыт. Приватный исходный HMAC CHR 2 после удаления временного SQL/state уже непереносим; он остаётся недоказанным. Полная двухузловая GRE приёмка, IPv6 readiness, IPsec SA и forwarding этим прогоном не закрыты.
Предыдущая проверка после восстановления лимита: протокол. Все 27 backend-профилей, MCP SQL/HTTP, SQL /logs, настоящий dump/restore и tamper прошли. Финальные GRE query/fallback проверены отдельным SQL/HTTP/restore-прогоном; итоговый inventory — 323 инструмента, 162 mediated / 62 excluded / 38 pending. CHR whole-section GRE restore пока не принят: статическое происхождение не подтверждено, выполнение остановлено, отдельная подтверждённая очистка восстановила восемь baseline fingerprints и полный proof зависимостей; неизменяемая попытка. Полный план остаётся открытым.
mm_netflow_live_observe (traffic.flow.live.read) использует общий с REST /api/traffic/flow/live live engine. Возвращает 1–3 выборки с интервалом 2 секунды, rolling window 5 минут, полный DTO с ограничением массивов через offset/limit и пределом ответа 1 МиБ. SQL-область применяется до агрегации; scoped reads не используют глобальный кэш, смешанные пользователи со скрытыми привязками исключаются. Лимит четырёх одновременных наблюдений общий с REST SSE; слот освобождается при ошибке/отмене. Права проверяются перед источником и выдачей каждой выборки. Это конечное наблюдение, а не бессрочная MCP-подписка. Поля live/rate сохраняют семантику REST: наличие listener и ring/window estimates не доказывают свежесть exporter, полное покрытие или forwarding. Приёмка включает настоящий локальный REST SSE, SQL, меняющиеся ticks, cache/scope isolation, отмену и отзыв доступа; протокол.
Состояние на 24 октября 2026 года (UTC+7), ветка codex/mcp-foundation. Полный объём: итоговый план. Актуальное число обработчиков показывает GET /api/mcp/catalog; результаты отдельных приёмок приведены ниже с датами. План ещё не закрыт целиком; наличие обработчиков не заменяет сетевую приёмку и проверку покрытия всех REST-операций. SQL-проверка привязки OSPF-плана к замерам выполнена; прежнее ограничение запуска снято.
Запуск
- Установить зависимости и собрать backend:
npm install,npm --prefix backend run build. - Настроить PostgreSQL,
AUTH_REQUIRED=true, доверенные issuer/JWT secret и точныйCORS_ORIGINвbackend/.env. Без авторизации MCP возвращает 503. - Задать
MCP_PUBLIC_URL=https://manager.example/mcp. HTTPS обязателен за пределами loopback. Reverse proxy должен сохранять Host и обслуживать/mcp,/oauth/*,/.well-known/*. - Задать
MCP_STATE_DIRвне PostgreSQL и дампов, с доступом только сервисному пользователю. Здесь находятся AES-GCM ключ, поколение доступа и внешний журнал восстановления. Реплики backend должны использовать общее согласованное состояние. Потеря ключа делает зашифрованные планы/секреты/выгрузки недоступными. - Запустить backend: миграции 0015–0029 применяются штатным bootstrap. Открыть Система → MCP, включить MCP и создать ограниченное подключение. Токен показывается однократно.
По умолчанию MCP выключен. Подключению явно назначаются операции, серверы, срок и лимиты. Новые инструменты не добавляются в существующий доступ автоматически.
Подтверждённые права владельца действуют до истечения его JWT, максимум 24 часа (без exp — 15 минут). Затем доступ останавливается до «Обновить мои права» в разделе подключений. Обновление берёт текущие проверенные JWT-права и инвалидирует планы/допуски контроллера. Для мгновенного отзыва реализован подписанный webhook портала; отправитель и доставка в реальном окружении требуют настройки. Внешний журнал отзыва переживает restore старой БД.
Подключение AI-клиента
HTTP: Streamable HTTP endpoint /mcp, заголовок Authorization: Bearer <токен подключения>. JWT портала служит для web-администрирования; токены агента не принимаются обычными /api/* маршрутами.
Stdio: после сборки запустить npm --prefix backend run mcp:stdio с переменными MCP_URL и MCP_TOKEN. Мост использует тот же HTTP endpoint, разрешения и аудит. stdout содержит только MCP-сообщения, диагностика идёт в stderr. Не сохраняйте токен в Git или аргументах командной строки.
OAuth: зарегистрировать публичный клиент с точными redirect URI в настройках MCP. Реализованы discovery, authorization code + PKCE S256, согласие владельца подключения, resource binding, access token до 15 минут, ротация refresh token и отзыв семейства при повторном использовании. Динамическая регистрация не включена. Redirect требует HTTPS либо loopback.
Администрирование и операции
Раздел /mcp: обзор, подключения, симулятор прав, защиты объектов, обращения, планы/операции, дрейф, Route AI, настройки и OAuth-клиенты. Доступны проверка готовности подключения, временные токены до 24 часов, отзыв, ротация и аварийная остановка. Проверка готовности выполняет публичные SDK initialize/tools-list и проверяет доступ; приёмка внешнего клиента требует его реального подключения.
Права: mm:mcp:read, mm:mcp:admin, mm:mcp:approve, mm:mcp:pause; mm:settings:admin включает их. Административная выдача ограничена владельцем/администратором. Ошибки остаются видимыми; скрытая вкладка прекращает polling.
GET /api/mcp/catalog — точный актуальный реестр. Только implementation: available имеет обработчик и может быть выдано подключению. POST /api/mcp/policy/preview — гипотетическая симуляция; результат allowed не выдаёт доступ и не одобряет план.
Реализованы типизированные чтения и планы серверов, пользователей/привязок, Ethernet, bridge/ports/VLAN, IPv4/IPv6-адресов и маршрутов, tables/rules/VRF, RPF/hash policy, firewall, GRE, WireGuard, VXLAN, OSPF templates, BGP connections, IPsec peers, контейнеров и сертификатов. Сервисные инструменты охватывают backup, события, оповещения, планировщик и историю мониторинга. Наличие базового объекта не означает покрытия всех сценариев соответствующего раздела.
Пользователи — каталог /users, его серверные права и привязки интерфейсов. Это не аккаунты auth-portal или локальные пользователи RouterOS.
Логи используют существующий collector/PostgreSQL: поиск, summary, контекст, bounded follow, настройки и экспорт до 50 000 записей. Ограничение серверов применяется в SQL до выдачи/агрегации. Курсоры зашифрованы и связаны с подключением, фильтрами и поколением доступа. Зашифрованные выгрузки живут 15 минут и скачиваются через авторизованный API. CSV защищён от формул.
Изменение проходит подготовку, подтверждение и применение. План содержит конкретные ID, снимки, шаги, версию политики и срок. Исполнитель повторно проверяет доступ, атомарно резервирует бюджет, сохраняет intent перед записью и проверяет каждый результат чтением. Изменённый снимок отклоняет план. Idempotency key не повторяет запись. После потери процесса незавершённое действие становится unknown без автоматического retry. Общие PostgreSQL-блокировки сериализуют конфигурационные записи UI/MCP.
Общий RouterOS-клиент сохраняет аудит до отправки любой конфигурационной записи. Защищённые объекты нельзя обойти через старые REST-обработчики или scheduler: без проверенного плана неизвестная область зависимостей блокируется консервативно. Для глобальных сервисных изменений проверяется полный текущий каталог серверов; его изменение инвалидирует план. Подтверждение команды полного router restore отдельно помечается как acknowledgement/inconclusive, а не как проверенная связность.
Маршрутизация
- Метрики содержат реальные RTT/loss/DL/UL, отдельные времена ping/bandwidth, направление, интерфейсы, family и VRF. Неизвестные/устаревшие данные не получают выдуманный рейтинг. Новый ping сохраняет независимый актуальный bandwidth. Обратное направление меняет DL/UL местами.
- Community-план использует существующий генератор управляемых BGP-фильтров, проверяет gateway/принадлежность, unmanaged-конфликты и пригодность выбранного пути по свежим измерениям/SLA. Перед записью эта пригодность проверяется повторно без выбора другого пути. Отдельная таблица Community пока отклоняется: генератор приложения не подтверждает её изоляцию.
- OSPF-план сохраняет template ID и costs, учитывает peer ownership, instance/family/table и свежесть измерений. Снимки соседств, areas и instances собственного/зависимых устройств проверяются перед выполнением; срок пригодности измерений ограничивает каждый шаг. При apply рейтинг не пересчитывается. Равные costs задаются явно; локальный рейтинг не выдаётся за глобальный оптимум.
- После всех cost-записей повторно проверяется Full выбранных OSPF-соседей и Up включённых BFD-сессий с привязкой к адресам/интерфейсу/VRF; эти протокольные инварианты сохраняются в обратных native-планах. Для ECMP до записи проверяется точный resolved next-hop, после — active выбранных маршрутов. Обратный ECMP-план может намеренно вернуть один маршрут в неактивное higher-distance состояние, поэтому прежний active-инвариант на него не переносится; связность проверяется контрольными пробами. Подтверждённая потеря здоровья даёт partial, недоступный ответ — unknown; команды не повторяются. Расширенная сквозная/аварийная приёмка ещё не завершена.
- ECMP-план выравнивает distance выбранных активных управляемых маршрутов одного prefix/table и меняет подтверждённую устройством hash policy. Активность next-hop повторно проверяется перед записью. NAT/FastTrack/RPF не меняются автоматически.
- RPF требует подтверждения риска асимметрии; strict отклоняется при нескольких таблицах/VRF. VRF-план проверяет состав существующего управляемого VRF, конфликты и снимки зависимостей; скрытый route leaking не создаётся.
- Профиль создаётся в web-редакторе Route AI или через
mm_route_profile_save_plan. Владелец может проверить, подтвердить и применить план в UI. Контроллер хранит состояние в PostgreSQL, использует межпроцессный lease, исходные credentials/политику и допуск до 24 часов, ограниченный актуальностью прав владельца. Учитываются pin/exclusion/SLA, hysteresis, новые образцы, cooldown и часовой лимит. Изменения проходят обычные планы/подтверждения. Отзыв доступа, смена политики, истечение допуска, дрейф, изменение ожидаемого пути и неоднозначный результат останавливают профиль.
Конфигурация маршрута и наблюдение контрольных пакетов различаются. mm_route_path_verify использует ограниченные native ping/traceroute, зарегистрированные IP интерфейсов и порядок обязательных hops. При нескольких адресах требуется явный IP. В traceroute берётся последняя .section, секции не объединяются; пропущенные промежуточные hops остаются неизвестными (completeTrace:false). Это не доказательство пути всего пользовательского трафика.
Management-канал регистрирует человек: отдельный IP, зашифрованный секрет, срок до 24 часов и JWT, сверка стабильного RouterOS license ID. Алиас основного IP/другое устройство отклоняются; перед стадиями повторно проверяются срок, отзыв, доступность и идентичность. Физическую независимость пути подтверждает администратор: отдельный IP её не доказывает.
Community допускает ограниченную автономность только при явной политике, свежих метриках и прошедшей проверке пути, проверенных management-каналах всех зависимостей и отсутствии блокирующих защит. Остальные нативные сетевые записи требуют человека. Failover контроллера требует трёх разных подтверждённых отказов и свежего прошедшего резерва; unknown не считается отказом.
Автовосстановление Community отдельно включается человеком в сохранённом профиле. Бюджет резервируется вместе с исходной операцией. Возврат допускается только после подтверждённой записи и неуспешной проверки, при неизменных checkpoint/gateway, действующих допусках и ранее подтверждённом исходном пути. Сначала сохраняется recovery intent; unknown не повторяется. Исходная операция остаётся partial, даже если восстановление проверено.
mm_operation_reconcile читает состояние по зашифрованным checkpoints. mm_operation_recovery_plan готовит отдельный человеческий обратный план для проверенных native create/update без внешнего дрейфа. Для deletes и сервисов универсального inverse нет: нужен собственный revisions/restore либо явный отказ.
Новые сервисы, web UI и отзыв порталом
Настройки traffic/uptime/NetFlow и каталоги Ping/bandwidth-проб используют общие UI/MCP-сервисы. Полная замена каталога показывает удаляемые ID, проверяет все серверные зависимости/защиты и требует подтверждения. Смена параметров bandwidth сбрасывает прежние измерения; MCP ограничивает duration 3–30 секундами. Контроллер сам bandwidth не запускает.
NetFlow analytics/monthly выбранного сервера фильтруются в SQL до объединения потоков; глобальные topology labels не выдаются. Host status/reconcile используют настроенный локальный агент и сохранённую конфигурацию. Проверка apply требует reachable/interfaceUp/configMatches; несовпадение остаётся partial. Общие guards также охватывают CRUD серверов/пользователей, настройки backup/cert renewal/collectors и полный restore. Покрытие всех прочих DB/host-путей ещё не объявляется завершённым.
Обычный PATCH пользователя не принимает роли/права; для них есть отдельный административный инструмент. Исправлены creation defaults в Zod PATCH: имя пользователя не сбрасывает роль/привязки, имя сервера не сбрасывает пароль/endpoint/TLS. Привязки поддерживают реальные ether/bridge/vlan/vxlan/gre/wg/ipsec/other.
Временный grant сужает также каталоги, SDK tools/list, конфигурации профилей и содержимое старых планов/операций. Скрытые серверные привязки пользователя фильтруются с incomplete:true; чтение или отмена плана вне области grant запрещены. Для пользователя есть отдельный get по ID и каталог/состояние интерфейсов для привязок.
Настройки API-ping и Internet path используют общие защищённые сервисы. Статистика и pivot вызывают существующий SQL-алгоритм с обязательным serverId и периодом до 31 дня; native обновление интерфейсов ограничено этим сервером. По умолчанию, как в обычном UI, учитываются привязанные интерфейсы; явный iface выбирает конкретный интерфейс. Проверка двумя различными SQL fixtures подтверждает отсутствие чужих данных и native запросов.
Реестр backend/mcp-coverage.json охватывает 262 маршрута: 168 сопоставленных сервисных сценариев, 62 обоснованных исключения транспорта/авторизации/управления самим MCP, 32 ожидающих адаптера. Его показывает административный UI. test:mcp сверяет реальный Fastify route inventory с файлом; новый endpoint требует явной записи. Обновление inventory: node --import tsx backend/src/scripts/mcp-coverage.ts --update из корня. Скрипт сохраняет существующие решения, новые бизнес-сценарии остаются pending. Проверка реестра не выдаёт pending за готовую реализацию и не объявляет native CRUD заменой всех высокоуровневых REST-сценариев.
mm_server_wan_runtime_get использует общий с REST readWanRuntimeForServer: три native-чтения DHCP/address/route только выбранного включённого сервера. Возвращает IPv4/main, activeDefaults, defaultRouteStatus confirmed/none/unknown/ambiguous; ECMP или gateway-list не выбирает первый WAN. Для DHCP нужен bound, неоднозначные адреса не превращаются в единственный leasedIp. Состояние forwarding не подтверждается. MCP ограничивает страницы uplinks до 200, список адресов на uplink до 100, activeDefaults до 200 и показывает усечение; web API сохраняет поля прежнего DTO и дополнительные признаки достоверности. Неизвестные table/active/distance или противоречивые route flags не заменяются догадкой.
mm_bgp_sessions_get использует общие с REST reader/parser/poller для общего и per-server чтения: scope до опроса, пагинация серверов/сессий, failures/incomplete при частичном отказе, null для неизвестных счётчиков. mm_bgp_sessions_raw_get читает выбранный включённый сервер, добавляет его метаданные, ограничивает страницу и скрывает native-ключи до выдачи и аудита. Ошибочная структура или повторяющиеся ID не считаются успешным пустым parsed-каталогом. Raw — диагностические данные с общими ограничениями/redaction MCP, а не подтверждение передачи трафика.
mm_ospf_optimizer_analyze доступен наблюдателю с network:read. Общий с mm_ospf_optimizer_plan расчёт выдаёт до 50 строк рейтинга: текущий/предложенный cost, score, замеры, peer и срок пригодности. Он не создаёт план и не отправляет изменения. Для применения нужен новый план и человеческое подтверждение. Учитывается последнее наблюдение точного server/peer/interface/family/table; новое плохое или неподтверждённое наблюдение не замещается старым хорошим. Порог maxLossPct по умолчанию 1%, явный допуск передаётся в анализ/план. Этот анализ не объявляется эквивалентом legacy web optimize/preview с другой моделью измерений: отдельные REST-адаптеры legacy preview/apply реализованы через mm_ospf_application_preview и mm_ospf_application_optimize_plan.
Перед guarded-записями OSPF повторно проверяются зафиксированные observation ID/fingerprint/validUntil без пересчёта одобренного рейтинга. Модульная и SQL-приёмка пройдены: новое плохое наблюдение, изменение сохранённой строки и истечение пригодности после approval блокируют запись. Прежнее ограничение запуска временной PostgreSQL снято.
mm_geoip_get использует общий с REST buildGeoipStatus: локальные readers, состояние обновления и настройки. mm_geoip_settings_update_plan меняет enabled/updateIntervalSec через общий guarded-сервис, требует полный эффективный каталог серверов и подтверждение человека. Fingerprint содержит только настройки; служебные lastCheck/lastError/buildAt не отменяют план. Проверяется сохранение каждого изменённого поля. Перезапуск расписания при включённом GeoIP немедленно запускает проверку зеркала; это указано в предупреждении. Отключение не отменяет уже начатую загрузку. Успех операции подтверждает сохранение настроек, готовность баз проверяется отдельно; принудительный /geoip/update ещё ожидает адаптера.
mm_evobgp_settings_get возвращает baseUrl/enabled/secretConfigured без ключа и без создания строки БД. mm_evobgp_settings_update_plan принимает settings: {baseUrl?, enabled?} и необязательный apiKeyRef: UUID секрета владельца с purpose evobgp-api:<нормализованный URL> без serverId; null явно удаляет ключ. При изменении URL сохранённый ключ нельзя перенести без новой привязанной ссылки или явного удаления. План зашифрован, ключ скрыт в выдаче и журналах; смена ключа между подтверждением и применением инвалидирует план даже при неизменном secretConfigured. Сохранение проверяется включая ключ без его выдачи. Общий сервис REST/MCP соблюдает evobgp-settings:1, серверные защиты и аудит; бюджет учитывает до двух записей инициализации/обновления. Проверка доступности EvoBGP реализована отдельным адаптером общего с REST module GET; результат не доказывает передачу BGP-трафика.
mm_evobgp_catalog_get читает включённую интеграцию по сохранённым URL/ключу, с полным эффективным каталогом серверов до HTTP и SQL-агрегации. Общие с REST парсер, formatter и подсчёт уникальных серверов сохраняют неизвестный prefixCount как null. На каждую коллекцию действует offset/limit до 200, pages содержит total/nextOffset, catalogVersion позволяет заметить изменение исходных данных между страницами. Исходный ответ ограничен 8 MiB и 15 секундами вместе с телом; redirects запрещены, отмена вызова прерывает fetch. Ошибки не превращаются в пустой успешный каталог. Даже отражённый upstream ключ в обычном строковом поле скрывается перед выдачей/журналированием. Значения каталога описывают данные EvoBGP и локальные привязки фильтров; фактический обмен BGP-префиксами подтверждается отдельно.
Симулятор бюджета проверяет сумму уже использованного лимита и полной стоимости плана; точное заполнение оставшегося бюджета допустимо. Зарезервированная обратная операция включается в расчёт. Применение повторно проверяет бюджет под транзакционной блокировкой: расход после предварительной проверки не позволяет перерасход. SQL-приёмка проверяет отказ до создания пакетного плана и расход между подтверждением и применением.
mm_gre_catalog_get использует те же fetchServerFilters/pollGreCatalog, что /api/filters/gre-tunnels. Список разрешённых включённых серверов ограничивается до сетевых запросов: до 10 устройств за вызов, до 200 туннелей на страницу. Есть отдельные server/collection offsets, failures и incomplete; недоступный CHR не превращается в успешный пустой каталог. Выдаётся состояние IPsec без ключа.
mm_{filters,recursive_routes,firewall,wireguard,ipsec,gre}_revisions_get возвращают историю через общий listRevisions: сервер, раздел, источник, fingerprint, дату, заметку и число элементов. Максимум — 50 последних записей; достижение предела консервативно помечается incomplete:true. Права и server scope проверяются до SQL. Сохранённый payload не выдаётся: он может содержать ключи туннелей. Фильтры требуют mm:filters:read, остальные разделы — mm:network:read. Восстановление recursive-routes, filters, firewall и GRE реализовано отдельными общими REST/MCP-сервисами ниже; WG/IPsec restore остаются pending.
После изменений маршрутизации 18 октября повторно прошли все backend-профили, SQL/live logs и настоящий pg_dump/pg_restore на собственной временной БД (Regression failed profiles: none). После добавления GRE-каталога и истории отдельно повторены MCP-интеграция с PostgreSQL, сборка, unit-профиль и ESLint затронутых адаптеров. Web UI в этом блоке не менялся; девять E2E относятся к предыдущей проверке интерфейса.
Следующий блок добавил общие строгие сервисы mm_recursive_routes_catalog_get/mm_recursive_gateways_catalog_get: до 200 элементов на страницу, сохранение observed-кэша и ревизии только после подтверждения полного управляемого набора. Недостающие disabled/check-gateway читаются через native /get; неподдерживаемый owned-маршрут или ошибка опроса не подменяются кэшем. Состояния шлюзов — active/inactive/unknown.
mm_containers_state_get/mm_certificates_state_get используют общие state collectors с тем же отбором серверов до опроса и двумя уровнями пагинации. Сохраняются per-server ошибки, unsupported, частично доступные зависимости, неизвестные runtime/date/boot значения; native даты сертификатов требуют стабильного наблюдённого GMT offset. Все env values и произвольный cmd контейнеров скрыты до результата и аудита. Каталог контейнеров на реальных CHR подтвердил отсутствие пакета как unsupported; заполненные/частично доступные каталоги проверены локальным RouterOS-имитатором.
mm_server_snapshots_get читает до 200 последних snapshots через общий SQL-сервис выбранного сервера. mm_server_source_address_get принимает только ID зарегистрированного сервера: результат разрешения управляющего host имеет interfaceAddressVerified:false; DNS/управляющий IPv4 не заменяет проверку native адреса интерфейса.
mm_ecmp_preflight_get принимает семейство и 2–8 ID маршрутов. Читает десять фиксированных ресурсов: маршруты, family settings, filter/NAT/mangle/raw, routing rules/tables/VRF и connection tracking. Выдаёт ограниченный список выбранных маршрутов и findings с ID/числом затронутых объектов. Отсутствующие свойства, неоднозначные ID, недоступные ресурсы и неподтверждённый контекст остаются unknown. Неизвестные gateway не объявляются одинаковыми. Повтор next-hop или общего egress, NAT, FastTrack, mangle/rules, notrack, отключённый tracking и strict RPF требуют проверки человеком. Автоматическое изменение hash/NAT/firewall/RPF не выполняется; результат всегда review-required, networkValidation:not-performed, independentPaths:not-proven. Правила рассматриваются консервативно: совпадение реальных пакетов/переходов не вычисляется. Основания проверок: RouterOS IP Settings, Connection tracking, Packet Flow.
Read-only приёмка на обоих CHR 7.24.5: отчёт каталогов и preflight. В последнем запуске проверены 20 видов чтения, включая OSPF/BFD/firewall, интерфейсы Ping/speed-test и live-трафик выбранного интерфейса; все десять источников preflight IPv4/IPv6 доступны. Нет операций изменения устройства, 15 конфигурационных fingerprints на каждом CHR совпали до/после, включая восемь таблиц firewall. OSPF/BFD/firewall в этом запуске подтверждены как пустые; непустые/неизвестные/ошибочные состояния проверяются отдельно имитатором и SQL. Проверялись существующие маршруты, включая connected/разный контекст: их наличие не объявляется готовой ECMP-группой. Реальный NAT/FastTrack-трафик и физическая независимость этим отчётом не приняты. Временная БД не содержит историю приложения, поэтому пустой server history в стендовом отчёте дополняется SQL fixtures с двумя серверами.
Последний запуск этого отчёта завершён 18 октября в 11:25:43 UTC: на каждом CHR проверены десять видов чтения, включая новые WAN/BGP sessions/raw. Оба WAN получили ambiguous из-за нескольких активных default routes, BGP sessions подтвердили пустой список. Конфигурация не менялась; SSH-туннель закрыт. Обмен BGP-префиксами этим запуском не подтверждается.
Запуск read-only приёмки: node backend/scripts/test-mcp-postgres.mjs --chr-read из корня, с MMAPP_TEST_CHR_HOSTS, MMAPP_TEST_CHR_USER и при необходимости MMAPP_TEST_CHR_TUNNEL_PORTS. Пароль вводится в скрытом терминальном prompt. Работает тот же явный allowlist двух тестовых CHR и собственная временная PostgreSQL; mutating overlay-флаги в этом режиме не исполняются. После этого блока повторены build, MCP unit/integration, общие recursive/containers/certificates профили и ESLint. Полная backend-регрессия и restore выше относятся к предыдущему блоку.
mm_container_remove_plan использует тот же removeContainer/removeStoppedContainer, что REST remove: явный stopped, свежие повторные чтения и подтверждение отсутствия ID. Подготовка фиксирует конфигурационную идентичность контейнера и интерфейс-родитель (ID/name/type/disabled); обе формы защиты interface и native type участвуют в evaluator. Свободный cmd/env/mount config входит в fingerprint и не возвращается текстом. Missing disabled родителя сохраняется как null, без предположения о его состоянии. Native mm_container_delete_plan делегирует ту же подготовку и не обходит stopped/protections. Остановка, удаление интерфейса, mounts/env или root-dir не добавляются скрыто. Обратного плана удаления нет; unconfirmed read-back остаётся unknown, idempotency не отправляет повторный DELETE.
Start/stop/restart дополнительно сверяют fingerprint конфигурации и родителя перед командой и при проверке результата. Подмена контейнера при прежнем ID или изменение родителя после подтверждения блокируют исполнение; подмена после подтверждённой команды не считается успехом. Изменения проверены MCP-интеграцией с собственной PostgreSQL и имитатором RouterOS: running/unknown/error нельзя удалить, parent protections действуют для прямого/alias-инструмента и start/restart, stale configuration/state/parent отвергаются, restart остановленного/работающего контейнера исполняет нужные стадии, неуспешный read-back не повторяет DELETE. Реальная проверка удаления на двух CHR не выполнялась: пакет containers отсутствует, что зафиксировано предыдущей read-only приёмкой.
mm_recursive_revision_restore_plan требует serverId, revisionId и mm:network:write. Ревизия выбирается в SQL по ID/серверу/разделу, её payload сверяется с сохранённым fingerprint и существующей REST-схемой. План заменяет полный owned-набор recursive-routes: до 50 текущих и до 50 целевых строк. Чужие маршруты не удаляются; пустая ревизия явно удаляет весь owned-набор. Используются общие applyRecursiveToServer/executeRecursiveApply, создаётся metadata/revision с источником rollback, native ID и cache ID меняются. Поэтому ссылки BGP-фильтров rec:<cache ID> блокируют план; новые ссылки проверяются повторно перед записью, не переписываются скрыто. Фиксируются снимки маршрутов/таблиц/rules/VRF/адресов и конкретные интерфейсы gateway, учитываются серверные защиты полного сервисного изменения. Native effective flags читаются также перед REST-применением, чтобы omitted disabled/check-gateway не превращали корректный owned-набор в ошибочный.
Ревизия, набор и зависимости повторно проверяются при исполнении; непосредственно перед первым PUT ещё раз сверяется observed owned-набор. Только после native операций сохраняется cache/revision. Read-back сравнивает полный набор как мультимножество, включая дубли, явный ноль и disabled/check-gateway; новые ID и metadata country не считаются native-дрейфом. Nullable scope/targetScope сохраняют REST-смысл «не задано, применяются defaults RouterOS» и не объявляются точным восстановлением неизвестного старого effective scope. Ошибка проверки даёт partial, потеря подтверждения — unknown без автоматического повтора или универсального inverse. Изменения NAT/RPF/management-пути не добавляются; проверка трафика выполняется отдельно.
Для пакетного сервиса сохраняется рассчитанная сервером mutationCost: create + delete + одна запись metadata. Исполнитель проверяет её в лимите объектов и резервирует весь часовой бюджет до запуска, независимо от одного service-step. Нулевой/отрицательный/дробный, слишком большой или меньший числа шагов cost отвергается. Для прежних планов без этого поля сохраняется стоимость по числу шагов. Отказавшиеся/неопределённые операции не возвращают зарезервированный бюджет автоматически.
Обычный исполнитель передаёт общим RouterOS/application guards проверку текущего допуска: credential, owner freshness, версия политики, temporary grant и защиты проверяются также перед каждой записью внутри сервисного шага. Уже зарезервированный бюджет повторно не списывается. SQL-интеграция останавливает доступ сразу после первого PUT и подтверждает, что следующий DELETE не отправлен, исходный owned-маршрут сохранён, исход операции unknown и автоматического повтора нет. Уже отправленная запись не отменяется отзывом. Отдельный trigger-тест проверяет несоответствие cache при корректных native/revision данных: оно тоже не считается успехом.
Приёмка восстановления на двух CHR 7.24.5 — отчёт. Стенд сначала требует отсутствие прежних owned recursive-routes. Используется уникальная non-FIB таблица и один отключённый маршрут; человеческие планы проверены при distance 10→25, пересоздании ID, сохранении metadata и очистке пустой ревизией. Конфигурационные fingerprints маршрутов/таблиц восстановлены на обоих CHR. Трафик не переключался, connectivity/failover этим тестом не принимаются. Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-recursive-restore с теми же переменными подключения и скрытым вводом пароля. Перед каждым auto-approval стенд проверяет, что полный заменяемый набор принадлежит только его marker/table; неожиданное владение или дрейф блокируют работу.
После восстановления recursive-routes повторно прошли все backend-профили, SQL/live logs и настоящий terminal pg_dump/pg_restore (Regression failed profiles: none). Дополнение проверки отзыва внутри service-step отдельно подтверждено повторной полной MCP-интеграцией; сборка и unit/ESLint также проверены. Новые изменения UI отсутствуют, прежние web E2E в этом блоке не перезапускались.
В UI есть URL-фильтры обращений по подключению, инструменту, пользователю, серверу, состоянию и периоду; время последнего успешного обновления; сравнение исходного состояния и шагов плана с предупреждениями/зависимостями. Аварийная остановка выключает MCP и активные профили. Очередь ограничена 100 pending/running операциями, локальных исполнителей — два.
Для webhook настроить отдельный случайный MCP_PORTAL_WEBHOOK_SECRET от 32 символов на backend и портале. POST /_internal/mcp/portal/revocations, JSON до 4096 байт:
{"eventId":"<UUID>","userId":"<JWT sub>","type":"permissions.changed"}
Допустимы также user.disabled, sessions.revoked. X-MM-Timestamp — Unix seconds; X-MM-Signature — sha256=<hex HMAC-SHA256(secret, timestamp + "." + точные байты тела)>. Окно — ±5 минут. Доставка по HTTPS; неподтверждённое событие повторяется с тем же eventId/телом и новой подписью. Принятый повтор идемпотентен, другой payload с тем же ID отклоняется.
Отзываются credentials/grants владельца, незапущенные планы и контроллеры. Отсечка JWT сохраняется вне PostgreSQL и переживает restore; после отзыва нужен iat позднее события. Приёмник и его проверки готовы, но отправку событий из настоящего auth-portal ещё нужно настроить и принять. Один backend не может самостоятельно узнать о смене прав в портале.
Терминальное восстановление PostgreSQL
На backend нужны совместимые pg_restore/psql в PATH; для создания архива — pg_dump. Наличие restore-утилит проверяется до плана.
В настройках MCP администратор загружает PGDMP custom архив до 64 МиБ. Зашифрованный файл вне БД привязан к владельцу/поколению и живёт до 15 минут; одновременно до четырёх архивов. Модель получает archiveRef и SHA-256 для mm_database_restore_plan. Произвольный путь, SQL и загрузка моделью не поддерживаются.
Требуются settings admin, глобальный доступ ко всем серверам и отдельное подтверждение. Учитываются защиты всех доменов и legacy REST. Исполнитель не удерживает обычный request admission: exclusive gate дожидается запросов/consumers, затем повторно проверяет допуск, одноразово помечает архив и отзывает MCP-поколение до записи. Потерянная команда не повторяется.
Restore может удалить исходную строку операции. Человек читает квитанцию вне БД через UI либо GET /api/mcp/database/receipts/:operationId: running/applied/blocked/unknown. Ошибки миграций/журнала/перезапуска после подтверждённого restore показаны отдельно и не запускают retry.
Для настоящей изолированной restore-проверки задать MMAPP_PG_CLIENT_BIN с каталогом pg_dump и pg_restore PostgreSQL 18 либо поместить их в PATH и передать --restore в test:mcp:pg. Runner проверяет запуск обеих утилит до integration fixtures и при их отсутствии завершает прогон с очисткой своего временного кластера. Windows embedded PostgreSQL не содержит client tools. Некоторые Windows sandbox блокируют WAL rename: тогда кластер запускается вне sandbox, сохраняя ту же изоляцию БД.
Проверки
npm --prefix backend run test:mcp
npm --prefix backend run test:mcp:pg
npm --prefix backend run test:mcp:pg:all -- --restore
npx playwright test --config playwright.mcp.config.ts
npm --prefix backend run build
npx tsc --noEmit --incremental false
test:mcp:pg создаёт временный PostgreSQL 18, не использует БД приложения/локальную SQLite, запускает миграции, fake RouterOS и реальные HTTP/stdio SDK-клиенты, затем останавливает кластер. Проверяются OAuth/PKCE/replay, scopes, atomic budgets, approval, intent, idempotency, snapshot conflict, read-back, drift, persistent controller, runner leases и внешнее поколение доступа. :pg:all запускает backend-профили и SQL-тесты логов на отдельной временной БД и сообщает упавшие профили. E2E проверяют web UI с изолированными API fixtures, отдельно от протокольной интеграции.
Оставшиеся работы
Полная policy-граница и покрытие всех оставшихся DB/host и REST-операций; настройка отправителя webhook в настоящем auth-portal; приёмка подключения конкретных внешних AI-клиентов; полная трёхузловая CHR-приёмка Community/BGP/OSPFv2/v3/ECMP/VRF, аварий и сетевого восстановления. Серверный протокольный handshake реализован отдельно. Реализованные проверки и ограничения перечислены ниже; fixture не заменяет реальную сетевую приёмку.
Вкладка «Интерфейсы» предоставляет Ethernet, bridge/ports/VLAN, IPv4/IPv6-адреса и VRF. Серверы берутся из области собственного подключения, свойства — из типизированных схем backend; в план отправляются только изменённые поля. Создание, изменение и удаление требуют отдельной проверки/подтверждения/применения. Системные и динамические объекты доступны только для чтения. Пагинация ограничена 100 строками на запрос; смена подключения/сервера/типа создаёт отдельный контекст редактора.
Пройдены девять web E2E: доступ, ошибки/mobile, профиль с контрольными пробами, management с очисткой пароля, обратный план, URL-фильтры, изменение интерфейса, человеческая загрузка restore-архива и обзор плана. Базовая приёмка двух CHR и контроль пути/обратных планов на RouterOS 7.24.5 подтвердили approval, idempotency, read-back и полный lifecycle собственного отключённого bridge с обратным планом. Baseline интерфейсов восстановлен, IPv4/IPv6 routes не изменились. Пробы прошли в обоих направлениях, но JumpHost/ExitNode совмещены на втором CHR. На baseline нет OSPF neighbors/BGP sessions; это не полная приёмка переключения или failover.
Для повторения базовой CHR-проверки задайте MMAPP_TEST_CHR_HOSTS и MMAPP_TEST_CHR_USER, затем выполните npm --prefix backend run test:mcp:pg -- --chr. Пароль вводится в скрытом терминальном приглашении и не сохраняется в проекте. Скрипт допускает только два согласованных адреса стенда; PostgreSQL одноразовый. При необходимости MMAPP_TEST_CHR_TUNNEL_PORTS задаёт по одному локальному loopback-порту SSH-туннеля для каждого CHR. Неопределённый результат изменения не повторяется автоматически; cleanup ограничен собственным отключённым объектом с точным уникальным маркером.
Режим MMAPP_TEST_CHR_ROUTING=true дополнительно проверяет на каждом CHR собственную таблицу с fib=false без правил выбора и маршрут 192.0.2.0/24: создание отключённым, включение с изменением distance, отдельный обратный план и удаление. Таблицы и маршруты после очистки сравниваются с исходными fingerprints. В реальном RouterOS 7.24.5 обнаружен ответ fib:"" для выключенного FIB; он нормализуется только для этого поля, отсутствие поля остаётся неизвестным. Приёмка проверяет read-back конфигурации, а не прохождение трафика по тестовому маршруту.
Режим MMAPP_TEST_CHR_OVERLAY=true запускает отдельную двухузловую сетевую приёмку и сохраняет отчёт GRE/VRF. На каждом CHR создаются только собственные GRE, VRF, IPv4 /30 и IPv6 ULA /64; IPv6 должен быть уже включён. Проверяются connected routes исключительно в тестовой VRF и настоящие ping/traceroute IPv4/IPv6 в обе стороны. Отключение только тестового GRE на втором CHR должно дать явные sent/received и 100% потерь в обоих семействах, при сохранении REST-управления обоими CHR. Затем отдельный подтверждённый обратный план восстанавливает GRE, а обе контрольные пробы снова должны пройти. Приёмка прошла на RouterOS 7.24.5; RTT около 65–68 мс. Это отказ/восстановление одного overlay-линка, без проверки переключения на резервный маршрут или физической независимости управления.
Cleanup удаляет адреса → VRF → GRE через тот же executor; исходные fingerprints GRE/VRF/IPv4 и IPv6 addresses/routes/routing tables сравниваются на обоих CHR. Не меняются публичные интерфейсы, firewall или глобальные IPv6-настройки. Уникальный маркер и исходные fingerprints сохраняются до первой внешней записи, результаты проб — по мере выполнения. Для восстановления прерванного запуска есть явный MMAPP_TEST_CHR_OVERLAY_CLEANUP_MARKER=mcp-test-xxxxxxxx: сверяются точные имена, comment, адреса, состав VRF и оба GRE endpoint; неизвестные зависимости останавливают очистку.
Адресные/интерфейсные планы учитывают GRE, WireGuard и VXLAN и включают ссылки на родителей в проверку защит. Новая VRF создаётся перед первой существующей записью с сохранённым placeBeforeId в плане; порядок включён в fingerprint и проверяется после записи. Изменение порядка после подтверждения блокирует запись, проигнорированный устройством порядок даёт partial. Влияние порядка описано в документации RouterOS VRF. Автоматические dynamic IPv6 link-local адреса исключены из снимков изменяемой конфигурации: их появление/исчезновение при отключении собственного GRE не считается внешним редактированием и не блокирует обратный план. Явные link-local и остальные адреса остаются в снимках, список адресов по-прежнему показывает и автоматические записи.
Контрольная проба сохраняет packetCounts, когда получены корректные итоговые счётчики трёх запрошенных пакетов. Подтверждённый отказ требует завершённых sent=3/received=0 и согласованного результата ping. Неполные/переполненные/нечисловые счётчики, число пакетов вне запроса и противоречие между счётчиками и packet-loss не подтверждают отказ; эти случаи проверяются отдельными тестами.
MMAPP_TEST_CHR_OSPF=true вместе с overlay-режимом включает OSPF/BFD-приёмку. На собственном GRE создаются OSPFv2 и OSPFv3 instances/areas/templates и BFD-правила только для двух точных peer-адресов /32 и /128 в тестовой VRF. Пройдены четыре Full/Up соседства, реальные ping-измерения, cost 30→10 отдельно для IPv4/IPv6, сохранение cost другого семейства и обратное восстановление. Удаление выполняется в порядке templates → areas → instances → BFD rules; проверены fingerprints, затем пройдены прежние overlay fault/recovery и полная очистка. Это двухузловая приёмка cost и соседств, без доказательства глобального оптимума или переключения между независимыми физическими путями.
OSPF-оптимизатор сначала ограничивает templates по family/instance/VRF и связывает Full neighbor с тем же instance. При включённом use-bfd требуется единственная Up-сессия с совпадающими адресом соседа, интерфейсом и VRF; ID и наблюдаемые адресные атрибуты сверяются до и после записи, а также в обратном cost-плане. Неизвестный use-bfd читается через native /get, без предположения false. Отсутствующее/двусмысленное BFD-доказательство останавливает подготовку. BFD-конфигурации ограничены явными интерфейсами, одним peer /32 или /128, интервалами 1–60 секунд и multiplier 2–50; произвольного RouterOS script/command или ключей аутентификации эти схемы не принимают. Основания: OSPF instances, BFD.
mm_ospf_catalog_get вызывает тот же catalog service/parser, что /api/ospf/catalog, с предварительным ограничением серверов по эффективному подключению/grant. За обращение опрашивается не больше 10 серверов; серверы и пять коллекций имеют отдельную пагинацию, failures/incomplete остаются явными. Интеграция проверяет ровно семь native GET к одному разрешённому устройству, отсутствие запросов к скрытому серверу, пагинацию и ошибку опроса. Сервисные чтения legacy OSPF теперь покрывает отдельный mm_ospf_state_get, BFD — mm_bfd_sessions_get; optimize/preview покрывают отдельные mm_ospf_application_optimize_plan и mm_ospf_application_preview. Маскирование результатов дополнено OSPF auth-key и BGP TCP MD5 ключами, включая текстовые сообщения.
MMAPP_TEST_CHR_ECMP=true вместе с overlay-режимом запускает ECMP-приёмку: два адресных next-hop через собственный GRE и отдельный loopback peer в тестовой VRF. Для IPv4/IPv6 подтверждены переход distance 10/20→10/10 с обоими active, routed ping/traceroute и возврат 10/20 обратным планом при сохранении связности. Глобальная hash-policy не менялась; распределение потоков и независимость физических путей не проверены. Очистка вернула baseline bridge/VRF/адресов/маршрутов, затем прошли общий overlay fault/recovery и удаление контура. Интеграция отдельно проверяет исчезновение/подмену immediate-gw перед записью, потерю resolved после записи, отсутствие retry и защиты таблицы/IP settings. VRF alias использует общий native prepare, включая защиту удаляемого прежнего интерфейса; ECMP hash-policy, RPF и прямой IP settings план учитывают одинаковую singleton-защиту.
MMAPP_TEST_CHR_BGP=true вместе с overlay-режимом запускает BGP-приёмку. Создаются только собственные BGP instances и connections с частными ASN, точными локальным/remote адресами и явно заданными VRF/routing table. Пройдены установление двух сессий, согласование IPv4/IPv6 AFI, административное отключение одной connection и восстановление обратным планом. Конфигурация instances/connections/routes восстановлена; активных тестовых сессий нет. Исторический readonly session cache принудительно не очищается. Экспорт/import префиксов, Community и BGP failover этим тестом не приняты. RouterOS 7.24.5 может не возвращать vrf в session: в отчёте сохраняется null, а контекст подтверждается прочитанными instance и connection. Новые connection-планы требуют явного instance, ASN и точных peer/local IP одного семейства; широкие динамические listeners и auth-ключи схемой не принимаются. Изменение ASN/Router ID/disabled instance включает peer-зависимости в проверки защит.
mm_bgp_catalog_get использует общий BGP catalog poll/parser приложения, эффективную область серверов и ту же двухуровневую пагинацию. Тест подтверждает один GET к разрешённому серверу, отсутствие чужого опроса/метаданных и явный failure вместо успешного пустого каталога.
Нативные планы IPv4/IPv6-маршрутов, routing rules и BGP connections включают снимок таблиц и защиты используемых таблиц. Отсутствующая/отключённая таблица блокирует подготовку; удаление, переименование или отключение таблицы блокируют обнаруженные ссылки маршрутов, rules, VRF, OSPF instances и BGP connections. Эти зависимости повторно сверяются перед записью. Отдельная интеграция проверяет добавление ссылки уже после подтверждения плана. Для прерванной приёмки оператор может явно передать MMAPP_TEST_CHR_CLEANUP_MARKER=mcp-test-xxxxxxxx: удаляется только точно указанная пустая non-FIB таблица без маршрутов и routing rules; обхода общего executor нет.
Полная backend-регрессия после общих guards и каталогов проб прошла все профили; SQL/live logs на 5000 строк тоже зелёный. Некоторые старые SQL-ветки требуют собственного MMAPP_OWN_TEST_DB с особыми именами и без него явно пропускаются. Traffic-volume тест исправлен с учётом неизвестного membership в грубом bucket; алгоритм расчёта не менялся. Ранее пройдена миллионная проверка логов: вставка 19,3 с, история + summary 2,1 с на локальном стенде.
Восстановление БД через MCP реализовано с загрузкой архива человеком, отдельным подтверждением, эксклюзивным исполнителем и квитанцией вне PostgreSQL. Пройден настоящий pg_dump/pg_restore временной БД: исходная операция исчезает, квитанция сохраняется, старый токен отзывается, внешний отзыв JWT переживает старый дамп, повреждённый архив не применяется и повторный запуск не пишет данные. Ошибки журнала/миграций/перезапуска после подтверждённого restore — отдельные предупреждения, без retry.
mm_speed_test_runs_get читает историю скорости с SQL-ограничением обоих участников эффективной областью до пагинации и разбора метрик. Ноль и неизвестность сохраняются раздельно. mm_ping_source_interfaces_get и mm_speed_test_interfaces_get используют общие REST-сервисы: подтверждённые running/disabled, ограниченное чтение отсутствующего disabled через native /get, отдельный список неизвестных интерфейсов и статус пригодности IPv4-адресов. Каталоги не запускают нагрузочные пробы. mm_ping_probe_visibility_plan меняет только отображение Ping-пробы после человеческого подтверждения, проверки серверной принадлежности, защит, fingerprint и read-back.
mm_traffic_live_get использует общий с REST readTrafficLiveSample: один интерфейс либо полная сумма активных интерфейсов без loopback, от одного до трёх срезов с интервалом не меньше секунды и общим дедлайном 30 секунд. Это RX/TX интерфейсов роутера, а не оценка пропускной способности канала. Перед каждым native-запросом и выдачей результата повторно проверяются credential/grant, политика и конфигурация источника. Неполная сумма, ошибка авторизации или неизвестные flags не превращаются в ноль; при смене источника/отзыве дальнейший опрос прекращается. SQL-интеграция проверяет полный/частичный ответ, точный ноль, один интерфейс, bounds, отмену, серверную область, отключение, отзыв и дрейф. На обоих CHR подтверждён live-срез выбранного интерфейса; агрегат по всем интерфейсам отдельно этим стендовым отчётом не принимается.
Проверка подключения в web-разделе MCP выполняет официальный SDK handshake initialize и tools/list через фиксированный MCP_PUBLIC_URL. Для этого создаётся отдельный access-токен со сроком до 20 секунд и пустым grant: операции и серверы недоступны. Служебные credential/grant удаляются после успеха и ошибки, просроченные остатки восстанавливаются при следующей проверке этого подключения; повтор разрешён через 30 секунд. Дедлайн HTTP/тела ответа — 8 секунд, размер — 1 MiB, redirects запрещены. Успех требует пустого списка инструментов. Ответ protocolProbe отличает passed/failed/skipped и явно содержит clientCredentialsVerified: false: проверяется серверный транспорт, а не настройки конкретного внешнего клиента. SQL-интеграция проверила настоящий HTTP handshake, отказ операции пустому grant, очистку при успехе/исключении и cooldown; отдельный HTTP-профиль — deadline, malformed/oversize и redirect.
mm_evobgp_connection_check и REST-проверка используют общий ограниченный GET /v1/modules?limit=1: до 1 MiB за 15 секунд, без redirects, с проверкой схемы items. MCP требует полный эффективный каталог серверов до HTTP и принимает сохранённые credentials либо owner/destination-bound apiKeyRef для чернового URL. Ключ не возвращается в ответе и не пересылается на другой URL из сохранённых настроек. Проверка не сохраняет настройки, не возвращает upstream items и не утверждает работоспособность BGP/каталога. Изменение сохранённой конфигурации во время проверки отвергает результат. SQL-приёмка подтверждает scope, чужой/неподходящий secret reference, отсутствие записи, маскирование отражённого ключа, malformed payload и redirect.
После этого блока повторно выполнен test:mcp:pg:all на собственном временном кластере с настоящими client tools: все backend-профили и SQL/live logs завершены, Regression failed profiles: none, pg_dump/pg_restore и новая миграция readiness проверены. Backend build, frontend TypeScript и ESLint изменённых модулей прошли. Повторно пройдены девять web E2E; отдельная дополненная проверка подтверждает, что UI отображает protocolHandshake и clientCredentialsVerified: false. Read-only CHR-отчёт обновлён 18 октября, 15:26 UTC; конфигурационных операций и дрейфа baseline нет. Эти результаты не закрывают 82 pending REST-адаптер и отдельные сетевые критерии полного плана.
mm_ospf_state_get использует общий с шестью REST-чтениями сервис состояния и вынесенные модели OSPF/BFD. Возвращаются отдельные страницы neighbors/interfaces/instances/areas/BFD/routes каждого разрешённого сервера. Native ID обязателен до объединения IPv4/IPv6, дубликаты и недостоверные строки дают явный failure; отсутствующие данные не становятся cost=10, OSPFv2, нулевым счётчиком или BFD Down. Area ID и instance связываются по подтверждённым именам/ID, не по порядковому номеру; неоднозначная area остаётся неизвестной. mm_bfd_sessions_get выполняет только чтение BFD, без опроса остальных OSPF-ресурсов. Legacy REST сохраняет совместимые значения по умолчанию в своей проекции; MCP использует nullable observed-проекцию того же чтения. Интеграция подтверждает семь GET для OSPF и один для BFD, предварительное ограничение серверов, пагинацию, disabled и ошибки; отдельные проверки моделей сохраняют известный ноль и исключают desired interval из actual interval.
mm_firewall_state_get использует общий listFirewallAll с выбранными серверами до native-опроса. Читаются восемь IPv4/IPv6 таблиц и два address-list; rules/addressLists имеют отдельные страницы, ошибки конкретных источников остаются в failures. Enabled/disabled/dynamic/log, protocol и packets не подменяются legacy defaults: неизвестные поля возвращаются как null, известный ноль сохраняется. Отдельные matcher-поля сохраняют оба интерфейса и различают адрес/список, source/destination port. Подсчёт неизвестных flags/counters не означает, что правила проверены на реальных пакетах: packetMatchingVerified всегда false. Недостоверные ID/обязательные поля/дубликаты отвергаются по таблице. Observed revision сохраняется только при полном опросе и подтверждённых disabled/dynamic flags; неизвестные flags или partial не превращаются в готовый снимок. SQL проверил ровно десять scoped GET, paging, disabled/foreign, nullable flags/known zero, маскирование лишних полей и отсутствие предположительных ревизий. Сервисные планы изменения/восстановления firewall остаются отдельными незавершёнными пунктами.
После OSPF/BFD повторно прошёл полный test:mcp:pg:all, включая SQL/live logs и реальный restore (Regression failed profiles: none). После firewall отдельно повторены MCP unit/integration с PostgreSQL, профиль live-maps с legacy REST, backend build и ESLint изменённых модулей. Web в этом блоке не менялся; девять E2E и отдельная проверка readiness относятся к предыдущему блоку. Последняя read-only CHR-приёмка завершена 18 октября, 15:49 UTC, без конфигурационных операций и дрейфа baseline.
mm_firewall_rule_move_plan принимает serverId и move: {family, table, rosId, destinationRosId?}. Отсутствие destination означает конец таблицы; перенос перед собой или уже достигнутая позиция не создают план. Используется общий с REST moveFirewallRule: фиксированные пути IPv4/IPv6 filter/nat/mangle/raw, конкретные существующие native ID, подтверждённо статические source/destination и до 1000 правил в снимке. Omitted dynamic проверяется через native /get; неподдерживаемый/неизвестный ответ блокирует изменение. Сохраняется точный порядок и все нативные matcher-поля, включая поля вне UI-формы; packets/bytes исключаются из fingerprint. Изменение любого matcher или порядка после approval блокирует запись. Защиты всех строк таблицы и серверных зависимостей проверяются до исполнения, бюджет резервирует команду и ревизию. После POST сверяются порядок и полная конфигурация, включая идентичность источника; проигнорированная команда — partial, потерянный ответ — unknown, без повторной отправки. Статус сохранения ревизии возвращается отдельно и не подменяет проверку порядка. Автоматический inverse не создаётся: возврат готовится новым планом по свежему состоянию.
Общая блокировка приложения и сервера охватывает чтение, команду, read-back и ревизию также для прямого web-вызова. Источник повторно выбирается из БД под блокировкой; stale credentials/host/disabled не используются. SQL-проверка удерживает lease другим исполнителем и подтверждает отказ до POST, а также отказ до сети при изменённой конфигурации источника. REST отклоняет selectors со списком ID и перемещение перед собой до lookup устройства.
SQL/имитатор проверили scope, защиты соседней строки, дрейф дополнительного matcher, рост счётчиков между approval/apply, точный порядок, сохранение ревизии, no-op/dynamic, partial и idempotency. CHR-приёмка перемещения на двух RouterOS 7.24.5 завершена 18 октября, 16:05 UTC. Стенд требует пустую filter-таблицу и создаёт ровно три собственных отключённых правила в уникальной непривязанной цепочке. Проверены перемещение, отдельный план возврата порядка, отсутствие повторной POST-команды и удаление fixtures; исходные fingerprints восьми таблиц firewall восстановлены. Непустой общий MCP-каталог подтвердил flags false и настоящий ноль счётчика. Обработка реальных пакетов и влияние порядка действующих правил не проверялись. Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-firewall-move с теми же переменными подключения и скрытым вводом пароля; перед подтверждением move проверяется принадлежность всей таблицы только этим fixtures.
После move прошёл полный test:mcp:pg:all, все backend-профили, SQL/live logs и настоящий pg_dump/pg_restore (Regression failed profiles: none). Финальное расширение общей блокировки дополнительно проверено повторным MCP SQL/restore, live-maps и сборкой/ESLint; unit проверяет неполные обязательные поля и отсутствие отправки при неподтверждённой static identity. UI-компоненты не менялись.
mm_wireguard_state_get, mm_ipsec_state_get и mm_vxlan_state_get используют общие REST polling/parser по эффективной серверной области до HTTP. За сервер выполняются соответственно четыре, восемь и два GET, без фонового collector и сетевых изменений. Пустая область не превращается в глобальный запрос. Disabled/foreign проверяются до опроса; недостоверные native ID/дубликаты, неизвестный родитель WG peer, ошибка любого обязательного источника дают явный failure. В WireGuard родитель peer/адреса разрешается как по имени, так и по native ID.
WireGuard возвращает nullable flags, mtu/listenPort и счётчики: отсутствие bytes не равно нулю, неизвестный running/disabled не становится Down. addressStateVerified отдельно показывает подтверждение состояния адреса; адрес не объявляется доказательством связности. Есть отдельные страницы interfaces, peers и allowedIps (offset/limit, peerOffset/peerLimit, allowedOffset/allowedLimit). Приватные ключи и preshared keys не выдаются даже с network:write; ключи, отражённые источником в name/comment, маскируются до результата/аудита. Параметра includePrivateKey в MCP-схеме нет; конфигурационные secret exports требуют отдельного человеческого сценария.
IPsec сохраняет бизнес-каталог IKEv2 peers/сертификатов/клиентов приложения. Flags passive/disabled/trusted и наличие key pair могут быть null. Неоднозначное сопоставление активной сессии или неизвестное native state не выдаётся за offline; подтверждённая established-сессия остаётся известной даже при неизвестном состоянии другой сессии. Возвращаются clientsOnlineConfirmed, clientsSessionUnknown и unknownSessionStates. Настроенный сервер/сертификаты подтверждают только configuration-presence, не data plane. Дата сертификата передаётся как nativeExpiresAt с expiryTimestampVerified:false; за проверенной датой/часовым поясом следует обращаться к отдельному certificate-state инструменту. Clients имеют offset/limit, peers/certs — detailOffset/detailLimit. PSK и отражённые секреты исключаются. WG/IPsec чтение явно сообщает configurationHistoryUpdated:false.
VXLAN сохраняет строгую проверку VNI, destination port, flags, ARP/learning и принадлежности статических VTEP. Страницы туннелей и VTEP независимы (offset/limit, vtepOffset/vtepLimit). Legacy source-port placeholder не передаётся MCP как наблюдаемый UDP-порт; используется подтверждённый dstPort. RouterOS 7.24.5 на непустом отключённом VXLAN не возвращает l2mtu: общий сервис и web-схема теперь принимают l2mtu:null, без выдуманного MTU. Непустое некорректное значение по-прежнему считается ошибкой. Экспорт не добавляет l2mtu/предполагаемый MTU. Ни один из каталогов не объявляет наличие интерфейса/сессии проверкой forwarding.
SQL/имитатор подтвердили точное число запросов к одному разрешённому серверу, вложенные страницы, zero/unknown, static address state, PSK/private-key reflection, IKEv2 session ambiguity и неизвестный state, отказ источников, дубликаты и отсутствие чужого/disabled опроса. Read-only отчёт CHR обновлён 19 октября, 01:56 UTC: 20 видов чтения, без мутаций, с 15 неизменными fingerprints на каждом CHR. В этом отчёте VPN-каталоги пустые; непустые конфигурационные проверки выделены отдельно.
Непустая VPN-приёмка на обоих CHR завершена 19 октября, 01:47 UTC. Стенд отказывается от существующих WG/VXLAN/IPsec peer конфигураций, создаёт только собственные отключённые объекты с уникальным marker и точечным passive IPsec peer без сертификатов/identities/SA. Подтверждены реальные DTO, отсутствие сгенерированного приватного WG-ключа в ответе и аудите, destination port VXLAN и null для отсутствующего native l2mtu. После теста все три объекта удалены через проверенные планы; fingerprints WG/VXLAN/IPsec peer и IPv4/IPv6 адресов восстановлены. VPN-трафик, peers/SA и end-to-end forwarding этим конфигурационным тестом не принимаются. Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-vpn-catalog с теми же allowlist/tunnel переменными и скрытым вводом пароля.
Полная регрессия после VPN-каталогов прошла все backend-профили, SQL/live logs и настоящий restore (Regression failed profiles: none). В negative restore-тесте ожидание terminal receipt согласовано с положительным сценарием: до 60 секунд вместо 5; конечный blocked, неизменность БД/поколения и запрет повтора остались обязательными. Последние allowed-prefix страницы и обработка l2mtu дополнительно проверены MCP SQL, моделями, frontend TypeScript и сборкой/ESLint; web export/schema принимают null и не добавляют выдуманный MTU.
Основания сетевых проверок: IP Routing, VRF, Policy Routing.
mm_gre_state_get закрывает чтение REST /api/gre/tunnels через общий fetchGreNativeState: ровно три GET к GRE и IPv4/IPv6-адресам на выбранный доступный сервер. Пустая/disabled область не опрашивается. Native identity, уникальность имён, обязательные адресные источники и неоднозначные name/native-ID привязки проверяются до проекции. MTU, DSCP, флаги и keepalive возвращаются nullable; явный ноль сохраняется. Адреса имеют семейство, native ID, disabled/dynamic/invalid и отдельный configurationVerified; неизвестное состояние не выдаётся за подтверждённый адрес. Локальный/удалённый внутренние адреса из комментария выделены как непроверенные метаданные. Состояние running не доказывает forwarding.
GRE имеет независимые страницы серверов, туннелей и адресов (serverOffset/serverLimit, offset/limit, addressOffset/addressLimit), детерминированную сортировку и признаки неполной выдачи. PSK не выдаётся; известный PSK, отражённый в обычном поле, маскируется до аудита. Ошибка любого из трёх источников даёт безопасный failure вместо успешного пустого каталога. MCP-чтение не сохраняет secret-bearing конфигурационную историю, что явно отражено в configurationHistoryUpdated:false; существующий REST сохраняет прежний сценарий истории.
SQL/имитатор проверил три scoped GET, nested paging, неизвестные поля, отказы каждого источника, дубликаты, запрет чужих/disabled серверов, отсутствие записи ревизии и PSK в результатах/аудите. Read-only CHR обновлён 19 октября, 01:56 UTC: 20 видов чтения на каждом CHR и 15 неизменных fingerprints. Непустая приёмка расширена собственным отключённым GRE с MTU 1400 и keepalive 10s/10: после чтения GRE/WG/VXLAN/IPsec все fixtures удалены, шесть fingerprints восстановлены на каждом CHR. Это конфигурационная приёмка, передача трафика этим тестом не проверялась. Текущее покрытие: 110 mediated, 62 excluded и 82 pending REST-маршрутов.
После GRE-блока повторно выполнен полный test:mcp:pg:all -- --restore с явным MMAPP_PG_CLIENT_BIN: все backend-профили и SQL/live logs прошли, итог Regression failed profiles: none. Настоящие pg_dump/pg_restore и negative terminal receipt проверены на собственном временном кластере. GRE-модели, config-sync, MCP unit/SQL, финальный backend TypeScript и ESLint прошли. Оба CHR очищены, SSH-туннель закрыт; рабочая БД и production-развёртывание не затрагивались.
mm_firewall_rule_form_create_plan, mm_firewall_rule_form_update_plan, mm_firewall_rule_form_toggle_plan, mm_firewall_rule_form_delete_plan закрывают POST/PUT/PATCH/DELETE /api/firewall/rules через общий сервис writeFirewallRule. Вход: serverId, rule: {operation, family: ip|ip6, table: filter|nat|mangle|raw, rosId?, fields?, disabled?}; operation фиксирован выбранным инструментом. Для create/update fields соответствуют форме REST, включая TLS host и L7 protocol; update требует chain/action. Пустые строки и protocol=all сохраняют прежнее поведение формы — они не очищают matcher-поле на устройстве. Отдельные native-инструменты имеют собственные схемы и не объявляются эквивалентом этой формы.
Каждый план требует человека и сохраняет полный порядок/конфигурацию выбранной таблицы без packets/bytes. Update/toggle/delete требуют настоящего ID и подтверждения static (при отсутствующем флаге — native get). Ошибка/unknown не разрешает запись. Область и все зарегистрированные защиты сервера проверяются консервативно: Firewall может влиять на управление и зависимости за пределами одной строки. Тот же сервис в REST удерживает общую application/server блокировку от свежего lookup источника до read-back и ревизии. Дрейф source/host/credentials, порядка или непрозрачного matcher блокирует команду; runtime counters — нет.
После create подтверждаются ровно один новый ID, добавление в конец таблицы и все заданные поля; update/toggle сохраняют остальные native matcher-поля и порядок; delete подтверждает отсутствие ровно выбранного ID. Bool yes/no и true/false нормализуются при проверке. Потерянный ответ не повторяется, проигнорированная запись становится partial. Ревизия записывается только после подтверждённого read-back и полного снимка; revisionRecorded отдельно показывает результат, неизвестные flags не превращаются в фиктивную ревизию. Прямой REST при неподтверждённой записи возвращает needsReview.
SQL/имитатор проверил четыре MCP-плана и четыре настоящих REST-обработчика, TLS/L7, защиты зависимостей, чужую область, stale matcher/source, конкурирующую блокировку, native static, partial, ревизии и idempotency; некорректные списки/path вместо ID REST отклоняет до работы с устройством. Приёмка Firewall CRUD пройдена на обоих CHR 7.24.5 для IPv4 и IPv6: собственная непривязанная chain, create/edit/toggle/disable/delete, отсутствие повторных команд и очистка с восстановлением восьми fingerprints на каждом CHR. Проверка реального packet matching этим сценариям не приписывается. Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-firewall-write с разрешёнными адресами CHR, tunnel ports и скрытым вводом пароля. Покрытие после Firewall rule CRUD: 114 mediated, 62 excluded, 86 pending.
После общего Firewall CRUD сервиса полный test:mcp:pg:all -- --restore завершился успешно: Regression failed profiles: none, все запускаемые backend-профили и SQL/live logs прошли. Проверены настоящие pg_dump/pg_restore временной БД, unit/service и прямые REST-сценарии, source drift и конкурирующий lease. Финальный backend TypeScript, ESLint и diff-check прошли. CHR fixtures удалены, baseline восстановлен, SSH-туннель закрыт. На этом этапе address-list CRUD и firewall revision restore ещё оставались pending.
mm_firewall_address_list_create_plan, mm_firewall_address_list_update_plan, mm_firewall_address_list_toggle_plan, mm_firewall_address_list_delete_plan закрывают четыре REST-операции /api/firewall/address-lists через общий writeFirewallAddress. Вход: serverId и address: {operation, family: ip|ip6, rosId?, fields?, disabled?}. Create/update используют fields формы REST (list, address, comment, timeout, disabled), update требует list/address. Непустые переданные значения меняются; пустые строки не очищают существующие поля. Снимок ограничен 1000 строками, проверка совпадающих кандидатов для create — 50 строками. Проверяются native ID/известное происхождение, общий серверный scope, консервативные защиты всех зависимостей, application/server locks и свежий источник перед командой. Планы требуют человека.
Timeout в каталоге — оставшееся время. Stable fingerprint сохраняет класс срока, ID, list/address, flags, creation-time и остальные native-поля; естественный countdown не ломает план. Для выбранной временной записи отдельно сохраняется окно абсолютного истечения, ограниченное временем запроса и секундной точностью native-значения. Срок повторно сверяется до intent и перед отправкой, а после записи — при read-back/verify. Продление/сброс вне окна блокирует старый план. Это интервальная проверка, не точное измерение миллисекунд: окна могут перекрываться в пределах точности источника/задержки запроса. Планы выбранной временной записи истекают до её нижней границы срока; слишком близкое истечение блокирует подготовку.
IPv4 host/CIDR/range и IPv6 host/CIDR сравниваются по адресной идентичности, без DNS-запросов и без смешивания mapped IPv6 с IPv4. Подтверждённая dynamic-запись не объявляется статической: удаление временных записей принимается при подтверждённом ID/сроке, а доступность их edit/toggle определяется RouterOS без повторной отправки. Ошибка/проигнорированная команда не превращается в applied; неоднозначные DNS-производные записи требуют сверки. Packet matching и DNS forwarding не проверяются. Временные записи хранятся в RAM; revision-снимок по прежним правилам хранит только постоянную конфигурацию, а revisionRecorded не означает сохранение timed entry. Основание: RouterOS Address-lists.
SQL/имитатор проверил четыре MCP-плана и четыре прямых REST-обработчика: канонизацию host, scoped/protected dependent rule, stale поля, partial/idempotency, finite create/delete, разрешённый countdown и запрет продления за пределами expiry window до команды. CHR-приёмка address-list, 19 октября 02:25 UTC: оба CHR, IPv4/IPv6 permanent CRUD, IPv4 range и IPv6 canonical CIDR, timed entry с native dynamic=true/timeout 1m58s–1m59s и delete после естественного уменьшения. Fixtures удалены; восемь firewall и два address-list fingerprints восстановлены на каждом CHR. Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-address-list с теми же разрешёнными hosts/tunnel ports и скрытым вводом пароля. Покрытие после address-list CRUD: 118 mediated, 62 excluded, 82 pending.
После address-list блока полный test:mcp:pg:all -- --restore завершён с Regression failed profiles: none: все запускаемые backend-профили, SQL/live logs и настоящий pg_dump/pg_restore изолированной БД прошли. Отдельные модели expiry/canonical address, MCP/REST integration, backend build/TypeScript, ESLint и diff-check прошли. CHR очищены, десять baseline fingerprints совпали на каждом устройстве, SSH-туннель закрыт. Весь план ещё не закрыт: 82 REST-адаптера, включая firewall revision restore, остаются открытыми.
mm_firewall_revision_restore_plan закрывает POST /api/firewall/revisions/:id/restore через общий REST/MCP restoreFirewallRevision. Аргументы: serverId, revisionId. Проверяются scoped revision lookup, её persisted fingerprint, строгая каноническая схема (явные rules/addressLists, включая намеренно пустые), до 50 желаемых и 100 текущих записей. Повреждённая/чужая ревизия не превращается в очистку. Новый снимок сохраняет native matcher/body-поля вне старой формы; ID, runtime flags/counters/creation-time и дублирующие modeled disabled/log в native payload не записываются. Неизвестный log исключает подтверждённую observed-ревизию; strict restore-reader при необходимости читает default flags через native get. Старые ревизии восстанавливают только сохранённую форму и явно показывают эту границу.
Исправлены порядок и multiplicity: восстанавливается весь статический набор IPv4/IPv6 filter/nat/mangle/raw и постоянных address-list, а не множество ключей. Native ID меняются. Динамические записи не удаляются, сохраняют взаимный порядок и после восстановления предшествуют новому статическому набору; их появление/исчезновение останавливает дальнейшие стадии. Countdown неперезаписываемых динамических address-list не считается дрейфом; их удаление/другие изменения конфигурации считаются. RAM/time-limited entries из ревизии не создаются.
Сначала создаются все новые записи с disabled=true; после каждого PUT проверяются новый ID, native invalid=false для правил, все переданные matcher-поля и неизменность прежних строк/порядка. Лишь после полной подготовки удаляются старые статические ID, затем включаются нужные новые записи; каждая DELETE/PATCH проверяется до следующей команды. Неподтверждённая подготовка не удаляет старый набор. Переключение не атомарно и может затронуть управление/соединения; обязательны человеческий план и все зарегистрированные защиты сервера. Общий application/server lease охватывает свежий source/revision lookup, proof, команды, read-back и rollback-ревизию. В бюджет включены все stage PUT, DELETE, enable PATCH и сохранение ревизии. Результат различает planned commandCount, acknowledgedCommands и verified completedCommands. Потерянный ответ не повторяется; partial/unknown требуют сверки, автоматического inverse нет.
SQL/имитатор и прямой REST подтвердили scope, corrupt/stale revision/opaque matcher, защиты, бюджет, дубликаты/порядок, dynamic preservation, disabled staging, stopped ignored/lost writes, отзыв между стадиями, точный read-back/ревизию и idempotency. Activation отдельно проверяется через настоящий локальный HTTP/SQL. CHR Firewall restore завершён на двух RouterOS 7.24.5 19 октября, 02:57 UTC: шесть собственных отключённых правил (accept/accept/drop для IPv4 и IPv6) с native connection-mark, два постоянных списка, затем отдельный план пустой ревизии. Десять baseline fingerprints восстановлены на каждом CHR. Packet matching/активация действующего Firewall этим стендовым сценарием не принимаются; activation проверен моделями и HTTP/SQL. Временные неуспешные диагностические запуски не объявляются успехом; итоговый отчёт complete=true подтверждает очистку.
Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-firewall-restore с прежними hosts/tunnel ports и скрытым вводом пароля. Стенд требует пустой Firewall; он отказывается подтверждать чужие/активные строки. После сбоя теста предыдущие отключённые fixtures могут быть очищены только по свежему подтверждённому плану, точному previous marker и сохранённому пустому baseline; это отдельная стендовая очистка, не автоматическое восстановление пользовательской операции. Покрытие после Firewall restore: 119 mediated, 62 excluded, 81 pending.
После Firewall restore выполнен полный test:mcp:pg:all -- --restore: все запускаемые backend-профили и SQL/live logs прошли, итог Regression failed profiles: none, настоящий pg_dump/pg_restore проверен. Финальные activation/counter/validity guards дополнительно проверены MCP HTTP/SQL и настоящим restore временной БД; invalid=false повторно принят на обоих CHR, отчёт обновлён 02:57 UTC. Entity/restore/polling модели, backend TypeScript, ESLint и diff-check прошли. Старый set-based planner заменён общим точным entry point; неизвестные flags не допускаются и прямым capture-helper. Все 12 конфигурационных REST-маршрутов Firewall имеют MCP-адаптеры. На момент этой проверки оставался 81 REST-сценарий и отдельная packet/сетевая приёмка полного плана.
NetFlow: экспортёры, клиенты и месячные отчёты
mm_netflow_exporters_get, mm_netflow_clients_get и mm_netflow_monthly_report_get закрывают три GET-сценария /api/traffic/flow/exporters, /clients, /monthly через общие REST/MCP readers. Требуются mm:traffic:read и явно разрешённые серверы. Серверная страница ограничена десятью источниками, клиентская — 50 пользователями; страны, сервисы и ASN месячного отчёта имеют собственные страницы. История выключенных серверов доступна, но выключенный сбор не означает недоступность устройства.
Область подключения, суженная временным grant, применяется до SQL-агрегации, разбора счётчиков и pending-строк. Пользователь со связью с любым скрытым сервером исключается целиком в SQL; его имя и скрытые привязки не попадают в Node или ответ. Отбор пользователя и проекция его разрешённых привязок выполняются одним SQL statement. Частичная серверная страница отмечается completeSourceSet:false. Приватные ключи, email и роли не входят в проекцию.
Окно чтения фиксирует обе границы; будущие и старые строки не входят в выбранный период. MCP ограничивает объём до 50 тысяч сохранённых/ожидающих строк на серверную страницу, 1000 привязок на пользователя и 10 тысяч агрегатных ключей месячного отчёта. Превышение даёт ошибку, а не обрезанный итог. Legacy REST сохраняет прежнюю ширину отчёта. Счётчики проверяются до преобразования из bigint и после сложения: отрицательные, нецелые и небезопасные значения отвергаются.
Суммы отражают сохранённые top rows по серверу/минуте, а не весь сетевой трафик. Дедупликация между интерфейсами и полнота покрытия не подтверждены. Клиентские значения относятся только к текущим named whole-interface ingress-привязкам: peer-specific связи не приписывают пользователю весь WireGuard-интерфейс, числовые ifIndex не получают неподтверждённого исторического имени. Для peer-only значений возвращается null; историческое владение интерфейсом не подтверждается. Средняя месячная скорость рассчитывается по полному календарному месяцу, включая ещё не наступившую часть.
Кольцо экспортёра показывает до 60 номинальных двухсекундных слотов, рассчитанных из поступивших flow bytes. Возможны padding-нули, timestamps слотов не подтверждены; отсутствующее кольцо даёт null, а не выдуманный ноль. В клиентском ответе оно явно обозначено как контекст сервера, не индивидуальная скорость клиента. availability:unknown, wireRateVerified:false и forwardingVerified:false сохраняются. Сохранённая peer-запись не подтверждает конфигурацию экспортёра на RouterOS. Некорректная запись выбранного peer даёт явное UNVERIFIED_SCHEMA; чужой malformed peer/ring не ломает разрешённый отчёт.
Модели и SQL/REST проверили скрытые/смешанные привязки, сужение grant, пустые страницы, историю отключённого сервера, будущие/pending строки, переполнение и предел группировки. Полный test:mcp:pg:all -- --restore прошёл со всеми запускаемыми профилями и SQL/live logs; последние проверки ring/peer отдельно прошли test:mcp:pg -- --restore с настоящим pg_dump/pg_restore. Чтения NetFlow не обращаются к RouterOS. Packet/forwarding-приёмка этого блока не заявляется.
Legacy-каталог контейнеров
GET /api/containers, GET /api/servers/:id/containers и mm_containers_state_get используют общий collector listContainersState. MCP выбирает разрешённые включённые серверы до создания RouterOS-клиентов, сортирует строки по native ID до пагинации и показывает per-device failures/unsupported. Legacy REST сохраняет прежний envelope и ошибку 502 при неполном чтении; отсутствие пакета по-прежнему даёт пустой legacy-каталог, тогда как MCP явно возвращает unsupported. Значения env и свободная команда остаются скрытыми в MCP и аудите.
Настоящие REST-обработчики и MCP проверены на одинаковом HTTP/SQL-стенде: идентичность объектов/статусов, неизвестный boot, различие legacy-secret и MCP-redaction, отказ env, отсутствие пакета, обратный порядок нативных строк и страница за концом каталога. Модели, loopback HTTP-профиль контейнеров, backend TypeScript и ESLint прошли. Это расширение каталога не подтверждает запуск/остановку контейнеров на CHR без установленного пакета.
Legacy-каталог сертификатов
GET /api/certificates, повторное чтение POST /api/certificates/refresh и mm_certificates_state_get используют один источник: /certificate и проверку стабильного gmt-offset до/после native-дат. Серверная область применяется до опроса; пустой выбранный набор не превращается в глобальный. Malformed ответ теперь даёт явный failure вместо успешного пустого legacy-каталога. Refresh не меняет конфигурацию устройства и не выдаёт сертификат.
Legacy DTO и его отображение дат сохранены. Более строгий MCP observed DTO отдельно сохраняет null/unknown при неподтверждённых сроках, статусе, key size или trust; он не наследует legacy fallback «valid» для отсутствующих свойств. Native/private key material не входит в оба DTO. Страницы MCP стабильны по ID, выборка за концом списка помечается неполной. HTTP/SQL проверил GET/refresh, совпадение ID/имён, фактический clock offset, отсутствие ключа, malformed failures и пустую область. Профиль сертификатов, NetFlow-модели, backend TypeScript, ESLint, MCP-профиль и SQL с настоящим pg_dump/restore прошли.
Сервисный каталог BGP-in
mm_bgp_filter_rules_get закрывает GET /api/filters/rules через общий readFilterRulesCatalog. Требуются mm:filters:read, операция routing.filters.catalog.read и разрешённые серверы. source:live читает выбранные включённые устройства; source:cache ограничивает SQL выбранными ID и позволяет посмотреть сохранённые правила отключённого сервера. Серверные страницы и отдельные страницы business/native/GRE-коллекций ограничены общими лимитами MCP. Пустая выбранная страница не запускает глобальный запрос.
Наблюдатель не заменяет кэш и не создаёт конфигурационную ревизию. Legacy live GET сохраняет прежнее обновление observed-кэша/истории, а запрос без serverId — чтение кэша. Ошибка или malformed live-ответ дают только кэш этого сервера с live:false, stale:true, явной ошибкой и nativeRules:null. Намеренный cache-read не доказывает свежесть: cacheFreshnessVerified:false. Некорректный serverId возвращает 400, отключённый сервер не опрашивается.
Нативные правила сохраняют ID, относительный порядок внутри bgp-in, исходный текст и enabled:null при неизвестном флаге. Отсутствующие ID/chain/rule и дубли ID отвергаются. Business parser возвращает эвристические Community/gateway/blackhole-подсказки, включая извлечения из disabled/unknown строк; это не вычисленная действующая политика. Переходы между chain, доступность gateway, сохранённые recursive references, обмен префиксами и forwarding не подтверждаются. GRE-проекция содержит только ссылки/адреса; точные состояния и MTU доступны через mm_gre_state_get, синтетические legacy defaults в этот ответ не переносятся.
SQL/REST проверил native порядок/флаги, pages, отказ чужого сервера до опроса, скрытый cache, отсутствие observer cache/revision writes, legacy refresh кэша, malformed fallback, отключённый источник и отсутствие ключей/PSK в ответе и аудите. Модели, config-sync, live-maps, MCP-профиль, backend TypeScript и ESLint прошли; SQL-приёмка завершилась настоящим pg_dump/pg_restore. Отдельные старые own-DB ветки config-sync без их переменных не объявляются выполненными.
Повторная CHR-приёмка завершена 19 октября, 07:18 UTC: на каждом RouterOS 7.24.5 пройден 21 вид чтения и IPv4/IPv6 ECMP preflight, совпали 15 исходных fingerprints. Новый BGP-in каталог подтвердил live/device источник, нулевой native-набор и отсутствие записи filters-кэша/ревизий; непустые правила, порядок и disabled/unknown проверены SQL/имитатором. Контейнеры на этих CHR остаются unsupported. Конфигурационные команды не выполнялись; туннель закрыт. Обмен BGP-префиксами и запуск контейнеров этим чтением не принимаются.
GRE: сервисные create/update/delete
mm_gre_tunnel_create_plan, mm_gre_tunnel_update_plan и mm_gre_tunnel_delete_plan закрывают POST/PATCH/DELETE /api/gre/tunnels через общий mutateGreTunnel. Нужны mm:network:write, разрешённая операция network.gre.*, сервер и подтверждение человеком. Создание принимает fields с именем/IPv4 outer endpoints и необязательным IPv4/IPv6 внутренним адресом; изменение и удаление адресуются по native rosId или однозначному имени. Переименование отдельно не выполняется. Условный «основной» адрес остаётся тем, который выбирает существующий GRE reader; остальные статические адреса сохраняются.
Перед изменением проверяются источник подключения, GRE/адреса, интерфейсный inventory, bridge ports/VLAN/list membership, VRF, маршруты, BGP filters/connections, OSPF templates, BFD configuration, routing rules и серверные DB-привязки пользователей/filters. Удаление с обнаруженной зависимостью или динамическим адресом, кроме автоматического IPv6 link-local, отклоняется. Проверяются все зарегистрированные защиты этого сервера. Непрозрачные native-поля входят в proof; runtime flags/счётчики и автоматические IPv6 link-local адреса не объявляются самостоятельной конфигурацией. Межпроцессные application/server locks общие для REST и MCP.
Создание/изменение сначала подготавливает GRE отключённым, затем меняет только запланированные статические адреса; требуемое включение выполняется последней командой. Удаление активного GRE сначала отключает его и затем удаляет адреса/интерфейс. Это не атомарное переключение, возможен перерыв связи. План включает от 1 до 50 native-команд; бюджет резервирует весь пакет и запись ревизии. Перед каждой командой проверяются свежий proof и действующий доступ; после команды — её точный эффект и неизменность остальных наблюдаемых объектов. Игнорируемая команда останавливает пакет как partial, потерянный ответ — как unknown; автоматического повтора или обратного плана нет. Обратное изменение готовится отдельно после сверки.
При PATCH сохраняются нативная запись keepalive, вторичные адреса, скрытый необязательный PSK и непрозрачные свойства. Частичное изменение непроверенного таймера отклоняется. Пустые comment/localAddress/PSK могут очищаться явно; очистка текста комментария сохраняет remote inner IP, пока те метаданные не очищены отдельно. Remote inner IP — метаданные, он не создаёт маршрута или удалённого адреса.
MCP не принимает сырой ipsecSecret: нужен ipsecSecretRef секрета владельца с точным purpose gre-ipsec:<serverId>:<name> и тем же сервером; удаление ключа задаётся clearIpsecSecret:true. Одновременно задавать оба нельзя. Ключ не входит в MCP-результат или аудит. Если чувствительное свойство скрыто и не меняется, оно не заменяется пустой строкой. Для явной записи нужен подтверждённый read-back. На RouterOS 7.24.5 пустой строковый get даёт []; это принимается как пустой PSK только после двух совпавших проверок локальной учётной записи/группы с sensitive. Без такого подтверждения пустой/скрытый ответ остаётся unknown. Явное включение FastPath при неизвестном PSK требует отдельной проверенной настройки ключа. Формат ответов/команд описан в RouterOS REST API, свойство PSK и его побочные IPsec-объекты — в GRE Properties.
Receipt отдельно содержит verified, числа planned/acknowledged/completed команд, afterFingerprint, revisionRecorded/revisionError. Проверяется сохранённая конфигурация; addressReadinessVerified:false и forwardingVerified:false сохраняются. Статический адрес отключённого GRE может корректно иметь invalid:true: это не превращается в утверждение о работоспособности адреса, DAD, SA или канала. Сбой сохранения полной ревизии после подтверждённого изменения не превращается в повтор native-команд.
SQL/реальный REST и модели подтвердили v4/v6 CRUD, сохранение secondary/opaque/PSK/timer, purpose/owner/server секрета, scope, бюджет/защиты, зависимости, дрейф, частичный результат, потерю ответа, idempotency и отзыв между командами. Полный test:mcp:pg:all -- --restore прошёл: все запускаемые backend-профили и SQL/live logs, настоящий pg_dump/pg_restore; последние PSK/readiness guards отдельно проверены моделями, MCP HTTP/SQL и test:mcp:pg -- --restore. В первом диагностическом полном прогоне restore был unconfirmed; новый изолированный полный прогон и последующая SQL/restore-проверка прошли, команды исходной операции не повторялись. Отдельные старые own-DB ветки без нужных переменных не объявляются выполненными.
CHR GRE обновлён 19 октября, 08:38 UTC: business CRUD и native aliases на двух RouterOS 7.24.5. Тест использует только собственные отключённые GRE и private benchmark/ULA адреса, включая явную пустую конфигурацию PSK как в web UI; меняет v4 на v6 с advertise:false, отдельно выполняет native rename/очистку comment/delete, удаляет fixtures и сравнивает восемь fingerprints. Очистка после неуспешного опыта — отдельные свежие подтверждённые native-планы по точному имени и известному ID текущего fixture, не повтор неизвестной операции. Непустой PSK/SA и передача пакетов остаются отдельной приёмкой.
mm_gre_update_plan/mm_gre_delete_plan сохраняют native-смысл одной команды над одним интерфейсом и используют network.gre.native.* исполнители. Для rename/delete должны отсутствовать обнаруженные пользовательские/filters ссылки, настроенные адреса и native зависимости. Удаление GRE не даёт неявного права удалить IPv4/IPv6 адреса; для пакетного изменения есть отдельные business-планы. Обычный scalar update связанного интерфейса допускается только с прежним подтверждением и проверкой защит. Source proof включает выбранные серверные DB-привязки и видимую native-конфигурацию, а также восемь IPv4/IPv6 Firewall таблиц. Порядок VRF/routing rules/filter/BFD/Firewall сохраняется; counters исключены, неподтверждённые значения не схлопываются в одинаковый null. Пустые comment и default local-address нормализуются отдельно; отсутствующий PSK не превращается в пустой ключ.
Стандартные aliases резервируют одну native-команду и запись ревизии. Прямой executeRosStep для GRE rename/delete, включая старые inverse/ROS steps, проходит тот же guard и точный read-back, сохраняя прежнюю стоимость одной native-команды без дополнительной записи истории. Перед dispatch повторно проверяются зависимости, включая вновь появившийся динамический маршрут, который намеренно не входит в конфигурационный fingerprint. Native игнорирование команды даёт partial; потеря ответа — unknown без повтора. SQL/реальный HTTP и модели проверили оба entry point, поздние DB/Firewall связи, границу адресов, переименование/очистку comment, opaque drift, counters, порядок, отсутствие скрытого каскада и no replay. MCP SQL с настоящим pg_dump/pg_restore, backend TypeScript, ESLint и профиль live-maps прошли; расширенная CHR-приёмка подтверждает rename/comment-clear/delete на обоих устройствах.
Запуск: node backend/scripts/test-mcp-postgres.mjs --chr-gre-mutation с MMAPP_TEST_CHR_HOSTS, MMAPP_TEST_CHR_TUNNEL_PORTS, MMAPP_TEST_CHR_USER; пароль вводится скрытым запросом. Тестовая PostgreSQL изолирована от приложения.
В коде 305 инструментов; реестр содержит 147 mediated, 62 excluded, 53 pending из 262 REST-маршрутов. Дополнительные BGP export-план и observer префиксов не закрывают отдельные legacy REST endpoints. Модели/coverage, финальные SQL/restore и профиль traffic-rate серверной/пользовательской истории трафика прошли. Подробности ниже. Остаток плана и отдельная сетевая приёмка сохраняются.
mm_recursive_routes_get и mm_recursive_gateways_get используют общие readers legacy REST. Маршруты возвращают явные live/stale и ограниченный кеш выбранного сервера при неподтверждённом источнике; шлюзы сохраняют up/down/unknown. Пустой успешный ответ отличается от ошибки. MCP-чтение не обновляет кеш и историю, forwardingVerified остаётся false. Строгие *_catalog_get сохраняют отказ при ошибке источника.
Обновление REST-кеша рекурсивных маршрутов сохраняет логические DB ID, сортировку и country, включая native recreation. Неизменённые строки сохраняют updated_at. Явные DB ID допустимы только для выбранного сервера; copy не переносит чужие ID. Без ID используются точные совпадения, затем единственная пара префикс/таблица; неоднозначное сопоставление отклоняется. Маршрут с BGP-ссылкой rec: нельзя удалить или переназначить на другой префикс/таблицу. Изменение gateway/distance сохраняет ссылку. Для BGP и recursive writes действуют общие блокировки; отсутствующая/некорректная rec-ссылка не подменяется ручным gateway.
Приёмка стабильных ID и новых readers завершена на обоих CHR 19 октября 2026 в 11:56:57 UTC: отключённые маршруты в собственной non-FIB таблице, native recreation, повторные чтения с rec-binding и отсутствие observer metadata writes. Проверены исходные fingerprints и очистка; SSH закрыт. Отчёт: docs/mcp-chr-recursive-restore-acceptance.json. Передача пакетов этим тестом не подтверждается. Также прошли backend build, recursive/MCP модели, ESLint и PostgreSQL-интеграция с настоящим pg_dump/pg_restore.
mm_recursive_routes_replace_plan подключает полный apply/copy набор REST /recursive-routes: до 50 желаемых и 50 текущих управляемых маршрутов, обязательный список routes, включая явный []. Требуются scope сервера, право network:write, человеческое подтверждение и бюджет всех create+delete+metadata операций. Копирование не переносит DB ID с другого сервера. План фиксирует native-конфигурацию, таблицы/интерфейсы, кеш и BGP-ссылки; их дрейф блокирует выполнение. Ссылки rec: сохраняются при допустимом редактировании; удаление или смена префикса используемого маршрута отклоняются до записи.
Общий исполнитель recursive apply/restore после каждого PUT подтверждает новый маршрут, перед DELETE проверяет исходный объект и после него отсутствие ID. Проигнорированный PUT, повторно использованный ID или изменённый target останавливают пакет до удаления следующего объекта. Неизвестный ответ даёт unknown, подтверждённый частичный результат — partial; автоматически повторять пакет или выполнять универсальный inverse нельзя. Итоговая проверка native-набора, кеша и ревизии выполняется отдельно. Forwarding не заявляется.
Расширенная приёмка этого плана завершена на обоих CHR 19 октября 2026 в 12:07:12 UTC: редактирование отключённого non-FIB маршрута при существующей BGP-ссылке, сохранение логического ID, per-command read-back, пустой apply/copy-набор, затем восстановление пустой ревизии и исходных fingerprints. Отчёт обновлён тем же тестовым runner; стенд очищен, туннель закрыт. Повторены recursive/MCP модели, live-maps, build, ESLint, SQL-интеграция и настоящий pg_dump/pg_restore.
mm_backup_job_get читает реальную очередь REST /backups/jobs/:jobId, в том числе через stdio-прокси. Требуются backups:read и доступ ко всем серверам задачи; смешанная задача не возвращает даже общий прогресс. Проверяются актуальный каталог серверов, числа результатов и терминальный статус. Ответ содержит status/completed/total, признаки failures/upload errors и отдельные ограниченные страницы created/failures. Заметки, имена файлов/устройств, ключи S3 и тексты ошибок исключены; ошибка показывается фиксированным сообщением. Известный нулевой размер остаётся нулём, отсутствие сведений о локальном файле — unknown.
Источник этого статуса — process-memory (ephemeral:true): закрытие приложения и восстановление БД очищают задачи. Отсутствующая или неоднозначная задача не угадывается по событиям/файлам. Это наблюдение за REST-очередью, а состояние самого MCP-выполнения остаётся в mm_operation_get. Проверены настоящая REST-очередь с контролируемым исполнителем, pending/done/partial upload, scopes и отсутствие утечек в ответе/аудите, очистка при app close/restore, build, backup-профиль, SQL/MCP и настоящий pg_dump/pg_restore.
После блока recursive routes и backup jobs выполнена полная backend-регрессия test:mcp:pg:all --restore: все профили test:all, заключительный SQL logs и настоящий pg_dump/pg_restore. Итог Regression failed profiles: none, exit 0. Результат относится к этому состоянию; дальнейшие блоки проверяются отдельно.
mm_internet_path_latest_get подключает сохранённый Internet path из общего REST latest-reader. serverOffset/serverLimit выбирают видимый подграф, а offset/limit ограничивают GRE, probes, rulesets и вложенные rules/uplinks. Speed probes включаются только при двух концах внутри выбранного подграфа. JSON отсекается по server IDs в SQL до разбора, включая map keys; скрытые повреждённые записи с известным владельцем не попадают в модель. Непривязанные записи, повреждённые обязательные коллекции и дубли отклоняются. Старый JSON-string payload scoped reader не декодирует целиком; его REST-совместимость сохранена.
Ответ возвращает только разрешённые поля; GRE PSK, пароли серверов, комментарии/описания и тексты probe errors не выдаются. Ноль сохраняется, отсутствующие метрики остаются null. source:stored-application-interpretation, selectedSubgraph:true, live:false, currentRoutingVerified:false и forwardingVerified:false отличают старую интерпретацию коллектора от текущих сетевых измерений. sourceCollectionComplete описывает исходный сбор; incomplete учитывает страницы/отсутствующие серверы. maxAgeSec задаёт порог stale (по умолчанию 900 секунд); дата из будущего помечается clockSkew и stale. Этот снимок не заменяет ECMP preflight или проверку пути.
Для Internet path отдельно прошли модели, MCP/SQL-интеграция с реальным REST timestamp/parity, проверка scope до разбора hidden/mixed данных, отсутствие секретов в результате/аудите и запросов к устройствам, backend build и ESLint. Полная backend-регрессия выше была выполнена перед этим следующим блоком.
mm_backup_storage_update_plan подключает PUT backup storage через тот же updateBackupStorageSettings, что REST. Нужны backups:write, allowGlobal, все текущие серверы в scope и человеческое подтверждение. Полный каталог, storage-защита и защиты серверных зависимостей проверяются до записи. Дрейф конфигурации, ключа, выданной ссылки, серверов/remote-archive state или занятость созданием/синхронизацией блокируют выполнение. Timestamps и результаты наблюдающего S3-теста не превращаются в конфигурационный дрейф.
Секретное значение в settings запрещено. Новое значение передаётся только как secretRef, выданный владельцу подключения без serverId с purpose backup-s3:<endpoint или aws-default>|<region>|<bucket>, например backup-s3:https://s3.example.test|us-east-1|backups. Endpoint/region/bucket берутся из планируемой конфигурации с удалением внешних пробелов; URL с credentials/query/hash и разделитель | в region/bucket отклоняются. Без ссылки ключ сохраняется. Перенос сохранённого ключа на другое usable-назначение требует ссылки для нового назначения. Пустой bucket разрешает очистить неиспользуемые настройки без обращения к S3, но последующее восстановление usable-назначения снова требует подходящей ссылки. При существующих S3-архивах сохраняются прежние запреты смены provider/endpoint/region/bucket/path-style.
Приватный отпечаток секрета учитывает постоянный серверный ключ вне восстанавливаемой БД и назначение; сам отпечаток не выводится в план/аудит. Plaintext секрета не хранится в шагах плана. Ссылка повторно проверяется перед записью. После неё сравниваются вся конфигурация и ключ, включая непрошенные изменения полей; несовпадение даёт partial без автоматического повтора. storageTestVerified:false прямо отделяет сохранение от проверки доступности S3; для неё используется отдельный mm_backup_storage_test_plan. Смена подключения/ключа сбрасывает прежний результат теста по правилам общего REST-сервиса.
Для storage-плана прошли модели назначения/ключевого fingerprint, backups HTTP-профиль, build/ESLint и SQL/MCP: scope/approval, первичная настройка, ротация/перенос, invalid/deleted/foreign references, busy/catalog/key drift, защита архивов, игнорирование/непрошенное изменение поля и idempotency. Настоящий pg_dump/pg_restore также повторён после keyed-proof; последняя ветка очистки bucket проверена отдельным финальным SQL-прогоном. Внешние запросы S3 этим тестом не выполнялись. Полная backend-регрессия выше относится к более раннему recursive/backup-jobs состоянию.
mm_ospf_application_preview подключает POST /servers/:id/ospf/optimize/preview через общий reader рейтинга приложения. Scope ограничивает SQL probes и опрос OSPF Router IDs до чтения; peerServerIds позволяет выбрать подмножество разрешённых устройств (не более 10 вместе с источником). offset/limit ограничивают interfaces/changes. Источник и актуальные права проверяются перед каждым GET/POST и после анализа, сетевой timeout ограничивается остатком 45-секундного deadline. Отмена/ошибка закрывает запросы группы; отмена GET и ошибка конструктора соединения проверены отдельно.
Значения legacy-модели с её округлениями, минимумами и fallback вынесены в modeled, исходные метрики — в observed. proposalOnly:true, metricContextVerified:false, executionAvailable:false и forwardingVerified:false не позволяют выдавать этот рейтинг за проверенный путь или готовый план. История интерфейса использует только latest aggregate row с известными counters/continuity; первый/ошибочный sample и отдельный WG peer не становятся измеренной скоростью. При неизвестных данных observed остаётся null, даже когда модель использует fallback. Измеряемый mm_ospf_optimizer_plan с family/VRF и свежими наблюдениями работает отдельно. Legacy POST /ospf/optimize покрывает mm_ospf_application_optimize_plan: он заново готовит полный human-only план и не применяет read-only preview напрямую.
SQL-приёмка OSPF preview проверила REST parity, hidden/disabled probes, peer scope, известный ноль/unknown, continuity flags, страницы, пустой/повреждённый каталог, отключённый источник, отмену и остановку следующего peer после паузы. Прошли OSPF/transport модели, build и ESLint. Read-only приёмка на обоих CHR завершена 19 октября 2026 в 13:37:07 UTC: 22 сценария, 15 неизменных fingerprints, пустые OSPF templates. Отчёт docs/mcp-chr-catalog-acceptance.json; мутаций/планов записи нет, SSH закрыт. Непустой рейтинг принят SQL-стендом, forwarding и cost switching этим запуском не подтверждаются.
Финальные test:mcp (после обновления coverage) и test:live-maps выполнены, оба процесса завершились с кодом 0. Coverage подтвердил 292 инструмента, 137 mediated / 62 excluded / 63 pending. Предыдущая недоступность review из-за лимита аккаунта устранена: после проверки доступности аккаунта повторные запуски прошли штатную проверку разрешений. Обход проверки не выполнялся.
Повторная полная backend-регрессия после Internet path/storage/OSPF выявила зависимость границ разделов PostgreSQL от часового пояса сессии. ensurePartitionFor теперь передаёт явные UTC instants вместо date-only literals. Новый SQL-сценарий проверяет сутки, неделю, високосный месяц, последний millisecond/следующую границу и DATE-keyed aggregates при UTC+7, UTC и DST-зоне. После исправления test:mcp:pg:all --restore прошёл целиком: Regression failed profiles: none, exit 0, включая настоящий pg_dump/pg_restore и заключительный SQL logs. Build и ESLint прошли.
На разрешённом Debian-стенде отдельно выполнен read-only аудит PostgreSQL 18.6: timezone UTC, все 85 timestamp-разделов десяти родителей имеют обе границы в полночь UTC. Отчёт. Транзакция завершена ROLLBACK, SSH закрыт; deployment и изменение данных не выполнялись. Правка не перестраивает уже существующие разделы: установки с прежними границами не в UTC требуют отдельного плана переноса данных перед включением новой схемы создания разделов. DATE-keyed monthly parents не входят в этот timestamp-аудит.
Заключительный npm run test:mcp из корня прошёл: 9 браузерных сценариев, exit 0. Проверены выдача доступа/токена, видимые ошибки и узкий экран, SLA-план Route AI, скрытие management-пароля, отдельный recovery-план, URL-фильтры обращений, планирование изменения интерфейса, человеческая загрузка архива БД и просмотр исходного состояния/зависимостей/шагов до подтверждения. Playwright использует mocked application API: это проверка web-сценариев, а не настоящего портала. Сводный отчёт регрессии сохраняет команды, границы проверки и открытый остаток плана.
mm_traffic_servers_history_get, mm_traffic_server_history_get и mm_traffic_server_interfaces_get используют общие с REST readers сохранённых samples. Нужен mm:traffic:read; список выбирает только enabled-серверы, отдельная история допускает выключенный источник и прямо показывает disabled. range — 5m/15m/1h/4h/24h, по умолчанию 1h; отдельный сервер допускает interface. Список ограничен serverOffset/serverLimit до 10 устройств; каталог интерфейсов за 24 часа — offset/limit до 200 записей. Будущие samples, loopback и отдельные WG peer rows не становятся интерфейсным агрегатом.
Scope и временный grant ограничивают запросы samples, collection state и metadata до чтения. Набор больше 20000 rows на серверную историю или 100000 rows на интерфейсный каталог отклоняется целиком; частичная сумма не возвращается. После SQL снова проверяются актуальные права подключения/владельца и неизменность источника. Отмена, pause, owner permission removal и изменение host во время SELECT не выдают старый результат. Чтение не опрашивает RouterOS и не создаёт конфигурационных планов.
Скорости/peaks и каждое значение series возвращаются как null без соответствующей observation mask; подтверждённый ноль сохраняется. Raw error strings, server host/password/name/site, peer keys и скрытые/будущие interface names не отражаются. currentState, sampled/attempt/success/expiry timestamps отделяют сохранённые измерения от текущего состояния. Running/disabled интерфейса nullable при неизвестном statusKnown и описывают последний retained sample; current interface state не подтверждается. accountedRxGiB/accountedTxGiB — сумма пригодных сохранённых дельт, а не доказанный полный сетевой объём. Направление router-interface-rx-tx; дедупликация интерфейсов, полное покрытие истории, актуальность snapshot-status и forwarding не заявляются.
SQL/MCP проверил REST parity, известный ноль/unknown, aggregate/WG peer, hidden/disabled scope, grant narrowing, error/pending/stale, paging, future exclusion, 20001 скрытых строк и переполнение выбранной истории, source/permission/pause races, отмену и безопасный persisted request result. Общий traffic-rate профиль и SQL logs прошли в отдельной БД; после последних guards повторены MCP SQL и настоящий pg_dump/restore. Build, ESLint и test:mcp (295 tools, 140/62/60 routes на этом этапе) прошли. OSPF fixture приведён к недельному partition kind для traffic_samples. Полная регрессия и web-отчёт выше предшествуют серверной истории; пользовательские адаптеры описаны ниже. Forwarding этим чтением не принимается.
mm_traffic_users_history_get, mm_traffic_user_history_get и mm_traffic_bound_interfaces_get используют общий REST builder с заранее выбранным SQL-каталогом пользователей/привязок. Permission — mm:traffic:read. Eligibility, исключение mixed users с любой привязкой вне grant, user paging и выбранные bindings вычисляются одним SQL statement до JSON/hydration. Private permissions, комментарии и peer names не гидратируются; peer public key нужен только внутреннему расчёту конкретного WG peer и не выдаётся, в том числе внутри составного ID.
Окна range — 5m/15m/1h/4h/24h. Параметры serverId/serverOffset/serverLimit выбирают не более 10 серверов, включая отключённые для исторического чтения. У списка пользователей offset/limit (до 50) и bindingOffset/bindingLimit (до 200); у detail — userId и binding pages. У плоского каталога привязок отдельные userOffset/userLimit и offset/limit для bindings внутри выбранной страницы пользователей. totalBindingsInUserPage не объявляется глобальным числом привязок. Более 200 выбранных привязок одного пользователя или 20000 samples сервера отклоняют расчёт целиком.
metricsScope:selected-bindings, bindingCount/selectedBindingCount и completeSourceSet отделяют subtotal от полного набора разрешённых источников. Связи с историческим владельцем и дедупликация перекрывающихся интерфейсов не подтверждаются. accountEnabled не подменяет сетевое состояние, enabled WG peer не объявляется online без handshake. Скорости/peaks/series используют общую observation mask: известный ноль сохраняется, неизвестное остаётся null. includeUnbound для пользователей без привязок требует allowGlobal и включения всех текущих серверов в scope; по умолчанию false. Временный grant сужает eligibility, а изменение привязок/источника или прав после SQL блокирует ответ.
При проверке будущих samples обнаружено, что прежний REST reader мог вычислять неверный legacy rxNow из интервала вне окна. Общие readers серверов, интерфейсов и пользователей теперь по умолчанию ограничивают SQL сверху rangeEnd; финальный SQL проверил правильную скорость в REST и MCP после добавления sample из будущего. Это исправление не меняет расчёт корректных данных внутри окна. Расчёт кеширует историю только на один запрос, по одному чтению на сервер; пустой injected catalog не возвращается к глобальному listUsers.
Проверены REST parity, разрешённый WG peer без ключа/комментариев, unknown first sample, disabled server/account, nested pages, полный/неполный source set, hidden mixed user, narrowing grant, pre-abort, 201 bindings, глобальный unbound guard и перенос привязки в скрытую область во время SELECT. Observer-планов и native запросов нет; persisted results не содержат контрольных секретов. Финальные MCP SQL/pg_dump/restore, build, ESLint и модели/coverage (298 tools, 143/62/57) прошли. После восстановления лимита штатный review разрешил дополнительный запуск с последним window fix: traffic-rate и SQL logs прошли, Regression failed profiles: none, exit 0. Прежний отказ review не обходился. В owned traffic-status SQL teardown теперь ожидает завершение scheduler jobs/journal до закрытия pool; заключительный профиль не содержит прежнего сообщения Cannot use a pool after calling end. Отчёт.
mm_bgp_export_plan изменяет только output.redistribute одной статической BGP connection: connected, static или disabled. Одновременно нужны mm:bgp:write, mm:network:read и mm:filters:read; человеческое подтверждение обязательно даже при autonomous/explicit-allow. Широкие или смешанные существующие режимы отклоняются. Instance, connection, VRF и таблица должны иметь явный согласованный контекст. Переключение не включает отключённого peer. disabled отключает перераспределение, а существующие output.network, default-originate и filters остаются действующими.
План сохраняет источники connected/static обоих семейств, адреса, фильтры и граф используемых шаблонов в приватных HMAC proofs. Смена credentials/назначения после approval блокируется до обращения к новому адресу. Пустой успешный /get означает unset; значения разрешаются через шаблоны, циклы и неоднозначные родители отклоняются. Очистка, которая вернула бы экспорт из активного шаблона, запрещена. Если RouterOS не возвращает флаг dynamic, требуется положительный результат native static query с точным ID; отсутствие флага само по себе недостаточно. До 500 исходных маршрутов, 100 шаблонов, глубина 16 и до 1000 объектов зависимостей; действует также меньший лимит подключения. Public preview содержит происхождение маршрутов и nullable active, не утверждает, что они анонсированы. Секреты и исходный текст фильтров в proof не раскрываются.
Перед записью повторно проверяются источники, контекст, права и защиты, после неё — native read-back всей конфигурации. No-op не отправляет PATCH; ignored/unexpected write становится partial, потеря ответа — unknown, автоматического повтора нет. SQL-приёмка с настоящим pg_dump/restore проверила эти исходы, drift credentials/маршрутов/фильтров/шаблонов, conjunctive permissions, peer disabled, nil/static-query guards и отсутствие контрольных секретов в сохранённых ответах. Полная backend-регрессия после traffic/BGP прошла: 26 профилей test:all, дополнительный SQL logs, MCP SQL и настоящий pg_dump/restore; Regression failed profiles: none, exit 0. Последний static-query fallback отдельно прошёл build, ESLint и SQL/restore. BGP prefix/Community и forwarding принимаются отдельно по фактическим CHR-наблюдениям.
В реальной подготовке BGP-стенда исправлен read-back VRF с несколькими интерфейсами: RouterOS меняет порядок членов и может вернуть массив вместо CSV. Состав одной VRF теперь сравнивается как нормализованный набор; порядок самих VRF остаётся значимым, поскольку определяет приоритет. Пустой набор/none, дубли, неоднозначные значения и array/string parity проверены моделями и SQL. Первый native-прогон сохраняет исходный отказ и подтверждённую очистку.
Для RouterOS 7.24.5 unset D flag выбирается native query -dynamic с точным ID и AND; dynamic=false не совпадает с unset. Это следует семантике API query, а не предположению по одному отсутствующему JSON-полю. SQL-отчёт BGP export отделяет проверку конфигурационного исполнителя от сетевого результата. Проба BGP по IPv4 transport действительно получила IPv6-префикс, но с неактивным IPv4-mapped next-hop: negotiated AFI и наличие префикса не считаются активным маршрутом. Следующий стендовый сценарий использует отдельные connections по IPv4 и IPv6.
mm_bgp_prefixes_get — observer с совместными mm:bgp:read и mm:network:read. Вход: один serverId, family: ipv4|ipv6, явная table (default main), offset/limit до 200. Читает фиксированный native route view с фильтром таблицы, подтверждает её идентичность до/после и ограничивает весь ответ 10000 строками до пагинации. Достоверные BGP/dynamic origins и префиксы обязательны; неизвестное происхождение, смешанные flags, дубли IDs и переполнение отклоняют ответ целиком. Поля ответа ограничены ID/семейством/таблицей/префиксом, nullable active и distance; ключи, комментарии и сырые native поля не выдаются.
Изменение источника, pause, сужение политики или отзыв права владельца во время чтения блокирует результат. Отмена не отправляет следующий GET; in-flight GET использует abortable transport. Сохраняются время получения, fingerprint и страницы, но atomicSnapshot, sessionAttributionVerified, advertisedRoutesVerified и forwardingVerified остаются false. Это view установленной RIB, не полные BGP attributes и не привязка к конкретному peer. Проверены модели, SQL/настоящий pg_dump/restore, build и ESLint; SQL отдельно подтверждает, что owner/pause race достигли native чтения, без observer-планов и отражения секретов. Покрытие — 300 tools, 143/62/57 REST.
MMAPP_TEST_CHR_BGP_EXPORT=true вместе с BGP/overlay флагами включает двухузловую prefix-приёмку. На RouterOS 7.24.5 она завершилась exit 0 20 октября 08:18:38 UTC: четыре сессии (отдельный IPv4/IPv6 transport на каждом CHR), восемь человеческих export-планов, активные /32 и /128 в обе стороны через mm_bgp_prefixes_get, явный отзыв и повторный анонс. Остановка IPv4 peer сохранила IPv6; обратный ROS-план вернул IPv4. Общий GRE fault восстановлен отдельным человеческим service-планом: универсальный ROS-only inverse к GRE service-step неприменим. BGP baseline и все 20 fingerprints десяти ресурсов двух CHR восстановлены. Тест не менял настройки underlay/firewall и не очищал исторический session cache. Принят connected export; static export проверен SQL, реальная static redistribution этим прогоном не подтверждается. Community и независимые физические пути остаются отдельной приёмкой; передача контрольных пакетов проверена следующим блоком.
Дополнительный MMAPP_TEST_CHR_BGP_FORWARD=true сохраняет отдельный отчёт пакетной приёмки; он завершился exit 0 20 октября 08:28:01 UTC. MCP mm_route_path_verify проверил 18 состояний: 11 успешных IPv4/IPv6 ping 3/3 с подтверждённым traceroute до BGP loopback, 7 подтверждённых отказов 3/0 после withdrawal/peer stop/удаления connections. Повторный анонс и inverse возвращают передачу; IPv6 продолжает работать при остановке IPv4 peer. Прямой маршрут к test loopback берётся из BGP, обратный — из связанной GRE-подсети. Это двухузловые контрольные пробы, без утверждения о пользовательском трафике, независимых физических путях или полном транзитном failover. Все 20 fingerprints восстановлены, SSH-туннель закрыт. Предыдущие prefix/SQL-отчёты сохранены отдельно; false forwardingVerified в observer DTO остаётся корректным: сам route view передачу пакетов не проверяет.
Полная замена Community-фильтров и восстановление ревизии
mm_filter_rules_replace_plan / filters.rules.replace и mm_filter_revision_restore_plan / filters.revision.restore закрывают PUT /api/filters/rules и POST /api/filters/revisions/:id/restore через общий REST/MCP сервис. Нужны одновременно mm:filters:write, mm:network:read, mm:bgp:read; даже autonomous grant требует человека. Запечатываются исходный сервер, revision/checksum, metadata/native rule и зависимости GRE/recursive, BGP/templates, OSPF/RIP/IS-IS/select, адреса, статические маршруты, таблицы/VRF. Серверные защиты применяются ко всем стадиям, включая изменение только метаданных. requireUnbound дополнительно запрещает существующие routing contexts и чужие filters.
До 1000 стандартных Community, dependency rows и объектов защиты; тело до 64 KiB. IPv4/IPv6 gateway задаётся literal IP, recursive reference должен совпадать с сохранённым и native маршрутом. Один собственный bgp-in набор создаётся/заменяется/удаляется; чужие правила и порядок сохраняются. Неизменное native тело не отправляется повторно. После native read-back сохраняются cache/revision, затем проверяются все три состояния. Неподтверждённая запись не повторяется автоматически.
Компилятор использует документированные set blackhole yes и set gw-interface по имени интерфейса (RouterOS Route Selection and Filters). Native routing-filter не принимает script-комментарии #; descriptions/communityName сохраняются в scoped metadata и ревизиях, reader указывает annotationsSource. Имена GRE ограничены проверенными ASCII буквами/цифрами и _ . : @ / - с пробелами. Кавычки, $, обратная косая черта и разделители отклоняются до опроса/записи: RouterOS CLI escaping и native menu ID не являются надёжным представлением имени в этом языке. Интерфейс автоматически не переименовывается.
Native приёмка завершена на двух CHR RouterOS 7.24.5 20 октября в 14:30:15 UTC: создание, замена, повтор без PATCH, копирование метаданных, восстановление первой ревизии, literal gateway и GRE с пробелом в имени, многострочное описание. На каждом CHR восстановлены 11 исходных fingerprints. communityPropagationVerified и forwardingVerified остаются false: routing contexts отсутствовали, GRE был отключён. Диагностические неуспешные отчёты сохранены; отдельная recovery-приёмка подтверждает удаление оставшегося тестового GRE и восстановление baseline. Текущий реестр: 302 tools, REST 145/62/55 из 262; полный план остаётся открыт.
Сводка uptime в MCP
mm_uptime_overview_get / uptime.overview.read закрывает GET /api/uptime/overview общим readUptimeOverview. SQL ограничивает probes, samples и scheduler provenance выбранными серверами до чтения в Node. Серверные и probe-страницы независимы: до 10 серверов, 200 проб на страницу, 1000 проб каталога, 20000 samples проб суммарно на страницу и 20000 ресурсных samples на сервер. Диапазон 5m–24h ограничен с обеих сторон; будущие samples исключаются также в REST.
MCP не использует нулевые defaults и искусственно дополненную историю UI. Неизвестные RTT/loss/CPU/memory/uptime остаются null; настоящий ноль сохраняется. Последняя попытка отделена от исторического успешного fallback, указаны timestamps/возраст и состояние server.enabled. Просроченный fallback не возвращается. measurementKnown отражает сохранённый флаг и доступные overrides scheduler failures; nativeMeasurementVerified, currentStateVerified, atomicSnapshot и forwardingVerified остаются false. Это сохранённая история, не новый запуск проб и не доказательство текущего пути.
Исходная конфигурация probes и серверов, права владельца/соединения и pause повторно проверяются перед выдачей. SQL-приёмка проверила 20001 скрытый sample, реальные публичные пороги, ноль/unknown, страницы, старый/просроченный fallback, REST parity и будущие samples. Гонки source/probe/owner/pause и отмена происходят во время реально заблокированного SQL-чтения, что подтверждается pg_stat_activity. Ошибки provider и пароли не отражаются, observer не создаёт планов и не обращается к устройствам. MCP models/coverage, backend build, ESLint, SQL, профиль probes, SQL logs и настоящий pg_dump/pg_restore прошли. Покрытие: 303 tools, REST 146 mediated / 62 excluded / 54 pending из 262. Отчёт.
Сопоставление GRE hostname через менеджер
mm_network_hosts_resolve / network.hosts.resolve закрывает POST /api/network/resolve-hosts общим resolveNetworkHosts. Требуются явный global grant и mm:network:write, как у существующего REST endpoint. Конфигурация не меняется, поэтому инструмент доступен observer; разрешение других write-операций этим не предоставляется. До 32 входов: строгие hostname/IP, IDN через IDNA, case/IDNA dedup, literal IPv4 без запроса. Literal IPv6 возвращает null с unsupported-family, не попадает в DNS и не мешает остальному пакету.
Resolver работает на хосте менеджера. DTO явно не подтверждает resolver RouterOS, принадлежность адреса интерфейсу и forwarding. Кэш до 512 записей на пять минут является политикой менеджера, не DNS TTL. Один lookup ограничен ожиданием 2 s, пакет — 10 s; не более восьми реальных незавершённых OS lookup на процесс. Таймаут/отмена вызывающего не освобождает pending capacity до завершения настоящего lookup; повторный hostname использует тот же pending lookup. Timeout/busy/unresolved различаются, upstream error payload не выдаётся. Права/pause/политика и отмена проверяются между hostname и после ожидания. REST disconnect останавливает дальнейшие lookup без преждевременной отмены после получения POST body.
Модели с mock resolver и реальным локальным HTTP проверяют TTL/eviction, IDNA/dedup, retained pending capacity, общий deadline, revoke/cancel, отключение клиента и REST parity. SQL проверяет global/permission boundary, observer, строгие входы, owner revoke/pause и отсутствие планов; внешние DNS и RouterOS для этой приёмки не вызываются. MCP/coverage, build и ESLint прошли. Текущий реестр: 304 tools, REST 147 mediated / 62 excluded / 53 pending из 262. Отчёт.
Общий контроль после Community, uptime и DNS
Полный test:mcp:pg:all -- --restore завершился с кодом 0: все 26 backend-профилей присутствуют в логе, Regression failed profiles: none, MCP/SQL, настоящий pg_dump/pg_restore и SQL logs прошли. Финальные build, ESLint, MCP models/coverage и diff-check прошли. Отчёт. Текущий checkpoint — 304 инструмента и REST 147/62/53. UI не менялся в этой итерации; прежние браузерные сценарии остаются отдельной исторической приёмкой. Полная Community propagation, независимые пути и трёхузловая аварийная приёмка, остальные сервисные адаптеры и external portal/client acceptance по-прежнему открыты.
Локальная привязка input/output цепочки BGP
mm_bgp_filter_binding_plan / routing.bgp.filter.bind меняет ровно input.filter либо output.filter-chain одного подтверждённого static peer. Имена native свойств соответствуют RouterOS BGP. Требуются одновременно BGP-write, filters-read, network-read и человек, включая autonomous explicit-allow. Выбирается существующая цепочка; её код не меняется. Пустая chain очищает локальную привязку только при подтверждённом пустом наследовании. Никакого неявного refresh, изменения templates или redistribution нет.
Private HMAC запечатывает credentials/назначение, полную конфигурацию connection, все filter rules с порядком, используемые templates и граф наследования, исходный instance/VRF/table и защиты. Контекст подтверждается по name/ID и native /get, без угадывания main; local nil отличается от explicit empty. Один local override может перекрывать разные parent значения, но неоднозначное наследование без override и очистка в активный inherited filter отклоняются. До 100 templates/16 уровней, 1000 connections/filter rows/parent rows и объединённых объектов с дальнейшим policy cap. Права и защиты проверяются перед записью, включая no-op; источник с изменившимися credentials не опрашивается. Read-back сравнивает целевой binding и оставшуюся конфигурацию/зависимости; ignored/partial/unknown не повторяются. Общий static-peer reader используется также BGP export и положительно подтверждает отсутствие D-флага.
Native приёмка завершена на двух CHR 20 октября 18:24:44 UTC, exit 0. В собственном GRE/VRF проверены input на первом узле и output на втором: цепочка с заведомо несовпадающей Community отклоняла IPv4-путь; после снятия binding путь восстанавливался, IPv6 сохранялся. Каждый refresh выполнялся отдельными подтверждёнными disable/enable планами своего peer. Всего 26 BGP control-probe проверок: 17 с 3/3 и 9 подтверждённых отказов с 3/0, включая прежние withdrawal/session сценарии. Все 22 overlay fingerprints (11 на CHR) восстановлены; SSH закрыт.
Это проверка привязки и реального действия фильтра с implicit reject, а не приёмка отправки Community attributes. Native non-empty template inheritance, Community tagging/propagation, независимые физические пути и трёхузловая приёмка остаются открыты. SQL/HTTP отдельно проверили наследование/default/ID контексты, template cycle, strict args/права, human-only, credential/no-poll и реальный late fence после application intent, защиты для no-op, ignored/partial/unknown и idempotency без повторной записи. Все 26 backend-профилей, MCP/SQL, настоящий restore, SQL logs, модели/coverage, build и lint прошли. Реестр: 305 tools, REST 147/62/53; новый binding не выдаётся за отдельный legacy REST adapter. Сводный отчёт.
Export policy стандартных BGP Community
mm_bgp_community_policy_plan (routing.bgp.community.policy) создаёт, заменяет или удаляет одну управляемую цепочку mmapp-bgp-out-<policyId>. Требуются одновременно mm:filters:write, mm:bgp:write, mm:network:read, область выбранного сервера и подтверждение человека, включая автономный режим. Новый инструмент нужно явно добавить в разрешённые операции подключения.
Пример аргументов для плана, который помечает один IPv4-префикс:
{
"serverId": 2,
"policyId": "selected-export",
"rules": [
{
"prefix": "192.0.2.1/32",
"match": "exact",
"communityMode": "set",
"communities": ["64512:999"],
"action": "accept"
}
],
"defaultAction": "reject"
}
Вход — типизированные IPv4/IPv6 CIDR; адрес приводится к адресу сети. Для match: subnet можно ограничить minLength/maxLength. communityMode принимает keep, set, append, clear; Community — только пары uint16. action принимает accept, reject, continue. Continue разрешён только при изменении Community; reject не меняет атрибуты. Порядок значим, максимум 500 правил и 64 KiB скомпилированного тела. Пользовательский код RouterOS не принимается.
В плане previousPolicy показывает текущие типизированные правила, если native тело в точности воспроизводится этим компилятором. desiredPolicy показывает желаемый результат. Для неизвестного native кода previousPolicy: null, previousPolicyRecognized: false и отдельное предупреждение: смысл произвольного скрипта не угадывается, исходный текст не передаётся в preview. Это не снимает обязательного подтверждения человеком.
Цепочка начинает влиять на обмен после отдельного mm_bgp_filter_binding_plan с native ID существующего статического peer, direction: output, chain: mmapp-bgp-out-selected-export. Default reject отклоняет все остальные префиксы. Если цепочка уже привязана, её замена влияет на всех использующих её клиентов. Обновление существующей policy включает её; это отражено в плане. Перезапуск peer не выполняется автоматически.
Удаление: тот же policyId, action: delete, rules: [], defaultAction: reject. Сначала необходимо отдельными планами убрать привязки; проверяются native BGP connections/templates, другие routing clients и jump references. Чужой маркер, совпадение имени чужой цепочки, неоднозначные ссылки и непрочитанные зависимости блокируют запись. Пустой replace создаёт reject-all цепочку и отличается от delete.
До dispatch повторно проверяются credentials, конфигурация, зависимости, права, защиты и application intent; после записи проверяются native ID, включённость, тело, положение правила и неизменность остальных цепочек. Потерянный ответ не вызывает автоматическую повторную запись. Чтение RouterOS может убрать кавычки вокруг простого имени gw-interface: сравнение учитывает только эту наблюдённую форму, сохраняя строгое сравнение команд, значений, порядка и прочего текста. При добавлении/удалении policy RouterOS обновляет служебный .nextid у соседнего правила. Сравнение остальных правил после записи проверяет их фактическую последовательность и содержимое, исключая этот производный указатель. До записи он остаётся в raw source proof: внешний drift .nextid блокирует устаревший план.
На 21 октября типизированный compiler и SQL/HTTP проверки реализованы. Native lifecycle приёмка на двух CHR завершена 20 октября 19:44:22 UTC: exact IPv4/IPv6, subnet с диапазоном и одной длиной, set/append/clear, no-op без записи, удаление и совместная работа с существующей bgp-in. Все 22 fingerprints восстановлены. Это проверка синтаксиса и конфигурации. Передача Community, выбор маршрута и пакеты приняты отдельным двухузловым функциональным сценарием ниже; весь native harness ещё не завершён штатно.
Предыдущий полный сценарий 20 октября остановился до BGP: GRE control probe потерял 3/3 пакета, после чего все 22 baseline fingerprints восстановлены. Последующая диагностика, завершённая 20 октября 19:53:06 UTC, не меняла конфигурацию и показала 2/9 ICMP с первого CHR на второй, 8/9 обратно при интервале 1 секунда, RPF=no на обоих. Это наблюдение доступности стенда в указанное время; оно не подтверждает Community propagation и не заменяет повторную сетевую приёмку после стабилизации пути. SSH-туннель закрыт.
Глобальные счётчики разделов
mm_sidebar_counts_get (system.sidebar.counts.read) использует общий с GET /api/sidebar-counts сервис. Требуются явный allowGlobal и все права источников из каталога операции, включая settings/admin и чтение соответствующих разделов. Действует обычное наследование RBAC, в том числе settings/admin → users/read. Это сводка всех серверов; список serverIds не превращает её в сводку выбранной страницы. Для такого частичного чтения предназначены каталоги разделов.
Перед сбором проверяется ограничение в 100 записей серверов, включая выключенные. Отказ в области доступа/правах и превышение лимита не вызывают native reads. Одновременные разрешённые запросы разделяют сбор и его фактические startedAt/observedAt. Данные разных источников не являются одной транзакционной фотографией: atomicSnapshot: false.
counts содержит подтверждённые неотрицательные числа, включая настоящий ноль. Ошибка, неполный или недоступный дополнительный источник дают null; названия таких полей перечислены в unknownCounters, incomplete: true. Если основные SQL-счётчики не подтверждены, весь MCP-вызов завершается STATE_UNAVAILABLE. Исходные ошибки провайдеров не возвращаются. В REST неизвестные дополнительные поля по-прежнему отсутствуют, как до выделения общего сервиса.
Подсчёт пользователей выполняется через SQL COUNT по тому же каталогу; карточки, права и привязки пользователей для этого не загружаются. Операция не создаёт планы и не меняет конфигурацию устройств.
Актуальный срез: 328 инструментов; REST 168 mediated / 62 excluded / 32 pending из 262. Новый инструмент не выдаётся существующим подключениям автоматически. Двухузловая функциональная Community-приёмка принята в объёме ниже; весь native harness и остальные незавершённые пункты полного плана остаются отдельными задачами.
Чтение выгрузок логов через MCP
mm_logs_export создаёт зашифрованную CSV/JSON-выгрузку с маскированием секретов. mm_logs_export_read (logs.export.read) позволяет AI-клиенту получить её без браузерной сессии: передайте artifactId, затем повторяйте запрос с offset, равным предыдущему nextOffset, до complete: true. limit задаёт число исходных байтов, от 1 до 12000, по умолчанию 12000. Ответ содержит dataBase64, общий размер, SHA-256, имя, MIME и срок действия. Сначала соедините декодированные байты всех частей, проверьте размер/SHA-256, затем декодируйте UTF-8: граница части может проходить внутри символа.
Оба инструмента требуют отдельного разрешения операции и mm:servers:read. Файл привязан к создавшему MCP-подключению, точному набору серверов, версии политики и поколению доступа. Подписанные метаданные проверяются до загрузки ciphertext; текущие права и grants проверяются повторно после SQL и расшифрования. Чужой файл, суженный grant, отзыв права, pause, истёкший срок или изменение подписанной области не позволяют получить содержимое. Старые файлы без подписанной области нужно экспортировать заново. Инструмент читает только такие выгрузки логов; backup/restore-архивы этим способом не выдаются. Существующий HTTP download продолжает требовать пользовательскую авторизацию.
Общий REST/MCP экспорт ограничен 50000 событиями и 8 MiB: серверная область и фильтры применяются в SQL до проверки бюджета; превышение проверяется до передачи строк в Node. Проверяется также размер готового CSV/JSON. Сузьте период/фильтры при EXPORT_LIMIT (422). Одновременно на процесс допускаются два тяжёлых экспорта/чтения, без очереди; EXPORT_BUSY (429) предлагает повторить запрос позже. TTL файла — 15 минут. Для подключения допускаются 8 файлов и 24 MiB ciphertext, общая квота — 256 MiB ciphertext; проверка и сохранение атомарны под PostgreSQL-блокировкой. При EXPORT_QUOTA_EXCEEDED (429) дождитесь истечения файлов. Эти ограничения также учитывают прочие записи хранилища артефактов. REST CSV сохраняет колонку host; MCP сохраняет прежнее маскирование и формат колонок.
Повторный контроль underlay 20 октября 20:08:54 UTC прошёл без потерь: 9/9 пакетов в каждую сторону, без изменения конфигурации. На этом основании выполнен новый изолированный сценарий. На первом узле прошли IPv4/IPv6, на втором IPv4 вернул unknown без подтверждённых счётчиков; BGP-этап не начинался. Первичная очистка остановилась на STATE_CONFLICT. Отдельная очистка точного маркера завершилась 20 октября 20:15:11 UTC: все 22 исходных fingerprints восстановлены, новый fixture не создавался, SSH закрыт. Неуспешный прогон сохранён; Community propagation остаётся открытой.
Контрольный ping для допуска Route AI теперь требует завершённых счётчиков именно 3 отправленных пакетов. Ответ 1/1 или 2/2 не подтверждает путь даже при нулевой заявленной потере. Для unknown добавлены фиксированная причина и ограниченные числовые наблюдения счётчиков, без исходных сообщений устройства; непроверенная трасса отмечается TRACE_UNCONFIRMED. Подтверждённый отказ по-прежнему требует 3/0. Эти проверки принимаются отдельно от фактического Community forwarding на стенде.
После усиления допуска пути полный повтор 27 backend-профилей, MCP SQL/HTTP, real pg_dump/restore и SQL logs завершён успешно 21 октября. Сводная проверка. Для следующих native-запусков тестовый отчёт сохраняет стадии prepare/approval/apply/verification/terminal, planId/operationId и безопасный код ошибки; аргументы и ответы провайдеров не сохраняются. Изменение тестового журнала проверено сборкой и линтером, отдельный native-прогон с ним ещё не принят.
Приёмка выгрузок логов: полная регрессия 27 профилей, SQL/HTTP, настоящий pg_dump/restore, source/row/byte/quota guards и гонки отзыва доступа прошли. Native и внешние AI-клиенты этим отчётом не принимаются.
Последняя native Community-диагностика 21 октября: получатель действительно увидел 64512:999, но после входного изменения gateway маршрут в VRF стал unreachable без immediate-gw. Успех конфигурационного read-back не подтверждает forwarding. Отчёт с ограниченным RIB-снимком: обе BGP-сессии установлены, все 22 исходных fingerprints после очистки совпали; append/clear, gateway/blackhole и полная Community-приёмка остаются открытыми. Значение immediate-gw и флаги RIB описаны в официальной документации MikroTik. Конкретная причина неразрешения next-hop пока не установлена.
Приёмка публикации restore-квитанций: при временном Windows sharing denial ограниченно повторяется только атомарная замена уже подготовленного файла, без повторного pg_restore. Старый файл остаётся доступным. Реальная блокировка Windows, 27 backend-профилей и настоящий restore проверены. Точная причина прежнего исторического сбоя без OS-кода не утверждается; test-runner теперь фиксирует безопасные stage/code. Изменение порядка VRF отменяет старый MCP filter-план до записи. Синтаксис gateway@VRF для routing-filter отклонён CHR 7.24.5 и в рабочий компилятор не включён.
Защита cross-table gateway references: MCP учитывает IPv4/IPv6 gateway @table/@VRF при delete/rename/disable. Зависимый маршрут в main блокирует удаление VRF, даже если его собственная routing-table другая. Kernel dynamic self-routes не блокируют штатное удаление членства; настроенные static routes блокируют. В том числе проверяется появление ссылки после approval. Полная backend-регрессия 27 профилей, SQL/HTTP и настоящий restore прошли. Recovery marker581cb8ad подтвердил все 22 исходных fingerprints без нового fixture. Автоматический Route AI для non-main таблиц по-прежнему явно отклоняется и остаётся в незавершённой части плана.
Двухузловая Community-приёмка: IPv4/IPv6 set/append/clear, оба tag после append, positive native blackhole, AFI isolation и восстановление подтверждены 18 packet proofs (12×3/3 с трассой, 6×3/0). Исходный полный harness завершился ошибкой RouterOS 401 при BGP teardown. Отдельное recovery восстановило все 22 fingerprints; SSH закрыт. Весь harness со штатной очисткой, независимые пути и автоматический VRF Route AI этим отчётом не принимаются.
mm_netflow_talkers_get (traffic.flow.talkers.read, mm:traffic:read, server scope) читает основные разговоры из сохранённых NetFlow rows и pending. Общая REST/MCP проекция объединяет conversation keys, сохраняет точные bytes/packets и configured topN; offset/limit относятся к доступному top-списку, totalConversations — ко всем разговорам в выбранном retained окне. Scope/grants применяются до SQL и разбора счётчиков; 50000 строк на набор выбранных серверов, 1–1440 минут, до 10 серверов/200 items на страницу. История выключенного сервера доступна без опроса устройства. Глобальные runtime/listener/host сведения не выдаются. Ответ явно сохраняет incomplete/coverageVerified=false: retained ingress rows могут пересекаться по интерфейсам, bps — усреднение по всему окну; это не wire rate и не подтверждение forwarding. Поздний отзыв прав, отмена, pause и изменение источника/topN блокируют выдачу. Приёмка: SQL/HTTP, лимиты, реальные гонки доступа, REST parity, build/lint и все 27 профилей прошли.
mm_alerts_outbox_retry_plan (alerts.outbox.retry, mm:alerts:write, global scope) повторно ставит существующее unknown-уведомление Telegram в очередь. Нужны точные id/expectedVersion, acknowledgedDuplicateRisk=true и отдельное подтверждение человеком. План сохраняет исходные текст/адресата; новый текст или получатель через MCP не задаются и не возвращаются. Требуется весь текущий каталог серверов (предел источника 999; лимиты подключения могут быть ниже), включая явный global allow. Общий REST/MCP application guard учитывает protections. Приватный HMAC исходной записи (до 1 MiB) повторно проверяется под блокировкой, затем CAS и read-back проходят в одной транзакции. Изменение адресата/payload при записи откатывает транзакцию до доступности сообщения отправителю.
Подтверждение retry означает только постановку в очередь: операция applied, verification=inconclusive, verificationScope=acknowledgement. Фоновый отправитель может выполнить её позже; прежнее сообщение могло быть доставлено, поэтому повтор создаёт риск дубликата. После unknown результата требуется сверка состояния, а не автоматический повтор. С тем же idempotency key возвращается прежняя квитанция. Проверка подключения и права на новую запись не заменяют друг друга: ранее созданная квитанция может оставаться доступна после отзыва write-права, но новое изменение отклоняется. Отчёт приёмки.
OSPF cost writer усилен: ожидаемый исходный cost, приватная привязка endpoint/учётных данных изменяемого роутера для optimizer-плана, сверка актуального источника под application/router lock, два bounded raw GET и проверка всей коллекции native templates после PATCH, включая не редактируемые UI поля. Игнорирование записи, подмена полей и потеря ответа останавливают цепочку без автоматического повтора. routing.ospf.optimize имеет revision=2; после обновления операции старый план следует подготовить заново. Runner также проверяет уже queued старые ревизии. REST различает известный отказ до записи и unknown после записи.
Исторический OSPF-блок был остановлен лимитом автоматической проверки разрешений. После восстановления лимита прошли SQL/HTTP и полная регрессия, затем общий legacy ranker/apply был подключён к публичным MCP apply/restore: актуальная приёмка. Формула измеряемого optimizer v7 остаётся отдельной. Приёмка новых публичных legacy-команд на реальных CHR ещё требуется; успешный SQL-прогон её не заменяет.
После восстановления лимита обычная проверка разрешений разрешила повтор OSPF-регрессии: все 27 backend-профилей, latest SQL/HTTP primary credential/revision/old-queued guards, настоящий pg_dump/restore, tampered archive и SQL logs прошли с кодом 0. Принятая часть относится к shared cost-only writer и привязке изменяемого роутера; exact REST preparation adapter, peer/source graph и native CHR проверка этой версии остаются открытыми. Прежняя блокировка review снята штатно, без обхода.
Замеры маршрутизации теперь привязаны к обоим зарегистрированным устройствам и эпохе подключения (миграция0029). После изменения host/port/учётных данных/TLS/enabled нужен новый замер, даже если вернуть прежние параметры. Старые строки остаются в истории с sourceVerified=false; они не участвуют в оптимизации. Новые строки подписывают метрики, интерфейсы, family/table и время публикации с микросекундами. Внешняя замена базы/поколения доступа также делает старые подписи непригодными.
История возвращает sourceVerified, contextVerified и recordedAt; serverId фильтруется в SQL внутри разрешённой области обоих концов. Секреты и подписи в историю не выдаются. Изменение источника или отзыв доступа во время измерения, ignored/tampered INSERT и неполные счётчики ping не создают пригодных данных. Последний unknown не заменяется более старым успехом. Для IPv6 можно явно выбрать dstAddress на интерфейсе зарегистрированного peer; глобальный bandwidth-test по-прежнему не доказывает выбранный WAN.
Текущие ревизии: routing.ospf.optimize=3, diagnostics.bandwidth=2; старые планы необходимо подготовить заново. Backend-приёмка прошла с повторной проверкой отдельного logs-профиля. Native OSPF-приёмка этих ревизий прервана перезапуском второго CHR до OSPF preflight. Все owned объекты удалены; точное совпадение всех исходных baseline не подтверждено: у двух динамических адресов доказана только смена ID, две route baseline требуют отдельной сверки. Отчёт очистки. Полный REST optimizer adapter и граф уникальности Router ID остаются открытыми.
Текущая ревизия routing.ospf.optimize=4 связывает весь граф владельцев в области MCP-политики, включая невыбранные устройства: endpoints/эпохи/поколение доступа и native OSPF instances. Все кандидаты входят в target, лимит устройств и блокировку. Повторная проверка перед dispatch отменяет план при появлении дубликата Router ID, изменении каталога или источника. Отключённый опрос Manager не доказывает отсутствие роутера в OSPF: такой источник не пропускается молча, подготовка отклоняется до сетевого опроса.
План revision3 и ранее необходимо подготовить заново. Приватные HMAC не выдаются в preview/audit. Лимиты графа:1000устройств,10000native rows суммарно,1МиБ. Backend-приёмка revision4:27профилей, настоящий restore, три SQL/HTTP-роутера, реальная блокировка третьего кандидата и смена его пароля во время native HTTP-ответа. Exact REST preparation, контекстное разрешение одинаковых Router ID между family/VRF и native current-revision проверка остаются открытыми.
Ревизия routing.ospf.optimize=5 разрешает именованный Router ID (main и другие ссылки) через /routing/id, сверяя его фактический static/elected ID и disabled/inactive. RouterOS допускает IP либо имя ссылки в router-id; выбранное значение ссылки доступно как dynamic-id. Описание OSPF, описание Router ID.
Пропущенные параметры уточняются у устройства. Исходная конфигурация и effective identity запечатываются раздельно; смена выбранного ID после approval отменяет план до cost PATCH. Владельцы разделяются по OSPFv2/v3, а набор нужных соседей ограничен выбранными локальными instance/interface. Неизвестный источник не пропускается. Полное различение одинаковых Router ID между удалёнными VRF ещё требует двусторонней привязки соседства; имена VRF двух роутеров не считаются равными автоматически.
Backend-приёмка revision 5: все 27 профилей, SQL/HTTP с elected ID/версией/defaults/соседним локальным VRF и настоящий restore прошли. Read-only проверка CHR подтвердила реальный источник именованных ID без native записей, используя синтетический OSPF-потребитель при пустых реальных OSPF catalogs. Полная native OSPF cost/forwarding приёмка и точный REST-сценарий остаются открытыми.
Ревизия routing.ospf.optimize=6 определяет peer VRF по фактическому двустороннему Full и принадлежности обоих адресов нужным интерфейсам. Равенство названий VRF на устройствах не требуется. Изолированное повторение Router ID допустимо; несколько полностью подходящих контекстов возвращают MEASUREMENT_UNKNOWN. Preview указывает peer instance/VRF/interface, а метрика должна относиться к этому peer-интерфейсу.
Граф identities/neighbors/addresses проверяется до dispatch и после cost-записи. Если запись подтверждена, но соседство изменилось во время неё, результат partial требует сверки; тот же idempotency key не повторяет PATCH. В подготовке проверяются живой допуск, отмена и source drift между native чтениями. IPv6 scope и effective address flags проверяются, счётчики adjacency исключены из identity fingerprint.
Backend-приёмка revision 6 включает 27 профилей и дополнительную финальную MCP SQL/HTTP+restore проверку после post-write guard. Read-only проверка CHR читала настоящие источники адресов/флагов и Router ID без записей. При пустых реальных OSPF catalogs она не доказывает работающее соседство/cost/forwarding. Полная native приёмка, unnumbered-случаи без адресного доказательства, точный REST-сценарий и оставшиеся пункты плана не закрыты.
Обратный OSPF-план использует operations.recover=2: expected cost берётся из подтверждённого снимка после исходного шага. Сохраняются private source proofs и полный граф соседств; потеря peer-контекста отменяет обратную запись. Старые версии исходного действия и старые обратные планы, включая очередь, требуют новой сверки. Прямой и обратный PATCH, late peer drift, idempotency и version fences проверены через SQL/HTTP; все 27 backend-профилей прошли.
Неуспешная native приёмка подтвердила OSPFv2/v3 Full+BFD Up и IPv4 cost, затем выявила ошибку expected cost в inverse. Все 22 исходных снимка после очистки совпали. Повторная native приёмка исправления завершилась exit 0: 60 MCP-операций, четыре Full/BFD Up, cost/inverse для IPv4/IPv6, 3/0 при отказе и 3/3 после отдельного одобренного восстановления; все 22 снимка совпали, туннель закрыт. У восстановленной IPv6-трассы один hop неизвестен при подтверждённом конечном узле; полная трасса не заявляется. Сводная приёмка. GRE-пробы к соседнему адресу подтверждают connected-путь; пересылка по изученным OSPF-маршрутам остаётся отдельной открытой проверкой.
Пассивные шаблоны OSPF и revision 7
routing.ospf.optimize revision 7 допускает только подтверждённые непассивные шаблоны. Пассивный loopback не требует BFD для ранжирования рабочего GRE и не становится целью cost-записи даже при устаревшем Full. Неизвестный passive не считается false. RouterOS switch подтверждается native getter либо двумя полными взаимодополняющими presence queries; лимиты, отзыв доступа и source drift проверяются между чтениями. После обновления старый cost-план необходимо подготовить заново.
Режим стенда MMAPP_TEST_CHR_OSPF_FORWARD=true требует OSPF_SOURCES, OSPF и OVERLAY, использует разные локальные VRF, дополнительные loopback-префиксы и проверку активного изученного RIB-маршрута. Маршрут и метрика проверяются до cost, после cost и после inverse, затем выполняются MCP packet probes. Обратный путь проб идёт по connected GRE; независимые пути не заявляются. Предыдущая приёмка подтвердила начальные маршруты и 3/3 в обоих семействах/направлениях, затем остановилась до cost; все 24 baseline восстановлены. Полная повторная приёмка revision 7 завершилась exit 0: 86 операций, 16 изученных RIB и 16 проб 3/3 с полными трассами, passive обоих семейств, все 24 исходных снимка и закрытый SSH-туннель.
mm_ospf_route_proof_get (routing.ospf.route.proof.read, право mm:network:read) принимает явные serverId, prefix, table и interface. Возвращает ограниченные поля одного активного изученного маршрута, подтверждённую метрику и время получения backend. Семейство определяется по префиксу; неподтверждённый протокол, флаги, метрика, неоднозначность и иной immediate egress дают отказ. На сервер проверяется область доступа до опроса; между GET/getter и перед выдачей проверяются допуск, отмена и epoch источника, включая ABA. Raw RIB и непрозрачные поля не возвращаются и не попадают в журнал. forwardingVerified=false: для доставки нужны отдельные packet probes. Новое право операции необходимо явно выдать подключению. SQL/HTTP, настоящий restore, tampered archive, все 27 backend-профилей, build, types и ESLint прошли. Приёмка reader.
Шаблоны OSPF create/update используют revision 2. passive=false при создании опускает switch с обязательным чтением результата; при обновлении флаг снимается native /unset. Смешанные поля превращаются в отдельные шаги плана, включая обратное восстановление. Native switch-приёмка прошла для OSPFv2/v3: 22 операции и все шесть исходных снимков восстановлены.
Проверка BFD в optimizer выполняется для непассивных шаблонов с единственным Full-соседом в выбранном instance/table: это уже обязательное условие ранжирования. Поэтому посторонний LAN без Full и с неизвестным BFD больше не блокирует рабочий GRE. Неизвестный BFD у подходящего Full-кандидата по-прежнему даёт отказ. Совместимое уточнение revision 7 проверено SQL/HTTP, модельными тестами и всеми 27 backend-профилями; отдельный native сценарий LAN без Full не заявляется.
Удаление peer WireGuard
mm_wireguard_peer_remove_plan (network.wireguard.peers.delete, mm:network:write) готовит человеческое подтверждение удаления одного peer по стабильному native ID. REST DELETE и native alias ros.wireguard_peer.delete revision 2 используют тот же сервис. Старые native планы требуют подготовки заново. Проверяются защиты сервера и родителя, привязки пользователей к peer/целому интерфейсу и фактическое владение NetFlow; одно имя интерфейса не доказывает владение сервисом.
Приватный HMAC фиксирует источник, видимую конфигурацию интерфейсов/peers и зависимости. Ключи в ответ и журнал не передаются. Перед единственным DELETE проверяется отсутствие дрейфа; после него — сохранность родителя и остальных peers. Счётчики трафика не считаются изменением конфигурации. Потеря ответа оставляет unknown, неподтверждённое или побочное изменение — partial; повторной native записи нет. Результат отдельно сообщает, сохранена ли ревизия приложения. Универсального inverse удаления нет.
mm_operation_reconcile поддерживает этот сервис через запечатанные исходный и желаемый HMAC: читает состояние с проверкой допуска/отмены между запросами и возвращает matchesDesiredState / matchesOriginalState. Сверка не меняет состояние исходной операции, включая unknown, и не повторяет DELETE. Старый план без совместимого desired proof получает явный отказ.
Приёмка: все 27 backend-профилей, SQL/HTTP, настоящий restore и tampered archive, build и ESLint прошли. На CHR выполнены четыре MCP-операции с отключёнными собственными интерфейсом и peer; подтверждены один DELETE, отдельная read-only сверка, сохранность родителя и запись ревизии. Все четыре исходных снимка и приватный отпечаток восстановлены, адреса не менялись, SSH-туннель закрыт. Handshake, пользовательский трафик и внешние AI-клиенты этим сценарием не проверяются.
Cost/forward-приёмка revision 7 отдельно подтвердила 12 изученных RIB/packet proofs, метрики 60 → 40 → 60, разные имена VRF и 24 восстановленных baseline. Полный исходный запуск завершился ошибкой на последующем passive toggle; это не успешный полный harness. Новый полный запуск с публичным MCP reader и исправленным switch завершился exit 0: 86 операций, 16 RIB/packet proofs, cost/inverse/passive для IPv4/IPv6 и восстановление всех 24 baseline. Проверен MCP runtime с реальным RouterOS API; внешние AI-клиенты остаются отдельной приёмкой. Обратный путь контрольных проб — connected GRE; независимые транзитные и пользовательские пути не заявляются.
При native mm_operation_reconcile допуск и отмена проверяются до каждого snapshot/getter и перед выдачей; изменение источника, включая endpoint ABA, прерывает чтение. Проверяются также источники предыдущих native шагов перед общей выдачей. matchesVerifiedCheckpoint сравнивает видимую конфигурацию ресурса: comparisonScope=visible-resource-configuration. Это не удостоверение исходного устройства (originalSourceIdentityVerified=false) и не доказательство forwarding. Отдельный WireGuard service proof включает исходный источник. Проверки отмены/паузы/ABA используют изолированные SQL/HTTP сервер и подключение; исходная операция не меняется и запись не повторяется.
Приёмка native-сверки: изолированный SQL/HTTP-сценарий, все 27 backend-профилей, SQL logs, настоящий restore, tampered archive, build и ESLint прошли. Новая проверка native-сверки на реальном RouterOS отдельно не заявляется; live WireGuard service reconciliation зафиксирована в собственном отчёте выше.
Изменение peer WireGuard
mm_wireguard_peer_edit_plan (network.wireguard.peers.update, mm:network:write) принимает serverId, стабильный peerId и непустой строгий patch. Поддерживаются все 11 публичных полей REST: publicKey, allowedAddresses, endpointAddress, endpointPort, persistentKeepalive, comment, name, disabled, clientAddress, clientDns, clientEndpoint. Пустые строки передаются как очистка; приватные и preshared keys не принимаются. REST PATCH и native update alias revision 2 используют один сервис. Перенос peer на иной интерфейс не входит в этот PATCH и получает явный отказ.
План требует человека, запечатывает источник, видимую непрозрачную конфигурацию, привязки и NetFlow-контекст. Разрешены обычные изменения привязанного peer; смена его публичного ключа требует предварительного изменения привязки и не может присвоить чужую dangling-привязку. Защиты родителя и сервера обязательны. Выполняется один PATCH с проверкой сохранности остальных peers и приватных полей. Потеря ответа оставляет unknown, неподтверждённый эффект — partial; тот же ключ идемпотентности не повторяет запись. Ревизия приложения возвращается отдельным receipt, универсального inverse сервиса пока нет.
Keepalive на проверенном CHR после отключения отсутствует в списке, а native getter возвращает []. Одного отсутствия недостаточно: reader требует успешный nil-getter, полное разбиение всех peer ID двумя противоположными presence-запросами и совпадение приватного снимка после вспомогательных чтений. В proof различаются неподтверждённое отсутствие и подтверждённое отключение; отсутствующие числовые значения не выдаются как измеренный ноль. Явный 0 отключает keepalive согласно документации WireGuard; диапазон и default RouterOS описаны в справочнике MikroTik. Допуск, отмена и source epoch проверяются между native чтениями. mm_operation_reconcile сравнивает исходный/желаемый semantic proof без записи и изменения состояния исходной операции.
Первые native clear-запуски дали partial, корректно остановились и восстановили все четыре baseline; они сохранены отдельно. Исправленная CHR-приёмка завершилась exit 0: шесть applied операций, два PATCH, все 11 полей, очистка endpoint/port/keepalive, read-only сверка, один DELETE peer и восстановление четырёх снимков/приватного отпечатка. Интерфейс и peer были отключены, адреса не менялись, туннель закрыт. Приёмка handshake/пользовательского трафика и внешних AI-клиентов этим сценарием не заявляется. Финальный полный backend-прогон после исправления прошёл: все 27 профилей, SQL logs, настоящий restore и tampered archive; build/ESLint и diff-check успешны. Итоговая приёмка PATCH.
Удаление интерфейса WireGuard с зависимыми объектами
mm_wireguard_interface_remove_plan (network.wireguard.interfaces.delete, revision 1) подготавливает человеческий план для serverId и стабильного interfaceId. REST DELETE использует тот же сервис. Preview показывает упорядоченные команды и их стоимость: отключение включённого интерфейса, удаление peers, статических IPv4/IPv6-адресов и самого интерфейса последним. Лимит — 50 native-команд; запись ревизии учитывается отдельно. Native alias mm_wireguard_delete_plan revision 2 сохраняет удаление только пустого интерфейса и отказывается от каскада.
Привязки пользователей, NetFlow, защиты сервера/родителя/детей и ссылки в маршрутах, фильтрах, протоколах и интерфейсах блокируют удаление. Неизвестные состояния дают отказ. Проверка включает literal и RouterOS-escaped ссылки, IPv6 и неявные OSPF network selectors. Перед каждой командой заново проверяются допуск, источник, зависимости и приватный отпечаток конфигурации; после каждой команды требуется точное подтверждение ожидаемого состояния. Runtime-таблицы зависимостей читаются, но не выдаются за запечатанную статическую конфигурацию.
Потеря ответа даёт unknown, неподтверждённый либо посторонний эффект — partial; запись не повторяется. Read-only reconciliation сравнивает исходное, конечное и подтверждённые промежуточные состояния, сохраняя статус исходной операции. Универсальный inverse и автоматическое продолжение каскада не поддерживаются.
Приёмка DELETE: на CHR шесть applied MCP-операций, пять DELETE с проверкой после каждой команды, два peer и два статических адреса, подтверждённый отказ native alias от каскада. Все четыре исходных снимка и приватный отпечаток восстановлены, туннель закрыт. Родитель и адреса fixture были отключены. Полный прогон 27 профилей, SQL logs и настоящий restore/tamper прошли; после последнего уточнения UTF-8 parser отдельно прошли SQL/HTTP/restore, модель, build и ESLint. Forwarding, VPN handshake и внешние AI-клиенты этим сценарием не принимаются.
NetFlow: подробная аналитика в MCP
mm_netflow_analytics_report_get (traffic.flow.analytics.read, mm:traffic:read) использует общий REST analytics engine для выбранного serverId. Поддерживаются окно 1–1440 минут, user/interface filters, dedup/excludeMesh/excludeOverlay и страницы массивов. Это отдельный инструмент; прежний краткий mm_netflow_analytics_get сохранён. Новое разрешение не добавляется существующим подключениям автоматически.
Scoped режим задаёт сервер до SQL и pending-выборки, обходит общий REST-кэш, загружает только разрешённую топологию и исключает пользователей со скрытыми привязками. Peer-привязка не считается владением всем интерфейсом. Источник ограничен 20000 строками, страница — 100 элементами, ответ — 1 МиБ; topN источника и top-списки engine явно показаны. Для чтения лимита не загружаются настройки с ключами коллектора и не выполняется их инициализация. Будущие строки исключены из окна общего analytics engine.
Проверки доступа и источника выполняются между этапами чтения и перед выдачей; топология и topN сверяются повторно. MCP не запускает коллектор, RIPE-enrichment, native poll или запись конфигурации. Сохранённые суммы неполны по определению retained topN. Context rates вынесены отдельно как унаследованные REST-оценки с ring/window fallback, без подтверждения пользовательской атрибуции. Paths — предположение по текущей топологии; forwarding, историческое владение и end-to-end пути не объявляются подтверждёнными.
Приёмка аналитики: SQL/MCP runtime и сравнение с REST engine, скрытые серверы/пользователи/peer, изоляция кэша, filters/dedup/pages/future/limits, endpoint ABA, drift топологии, cancel/pause и отсутствие планов. Отдельный REST HTTP-запрос в новом сценарии не выполнялся. Полная регрессия 27 профилей, SQL logs, настоящий restore/tamper, build и ESLint прошли. CHR forwarding и внешние AI-клиенты остаются отдельными пунктами плана.
Карта NetFlow: предполагаемые связи и сервисы
mm_netflow_map_hops_get (traffic.flow.map.read, mm:traffic:read) использует общий REST map engine для обязательного serverId. Поддержаны окно 1–1440 минут, фильтры user/interface, dedup/excludeMesh/excludeOverlay. Основные массивы имеют offset/limit до 100; вложенные clients, country services/edges/paths — отдельные nestedOffset/nestedLimit до 50. pages содержит total/nextOffset каждого выданного массива. Ссылки на узлы могут выходить за страницу; граф не объявляется полным.
Сервер ограничивает SQL и pending до загрузки потоков. Топология включает только разрешённые серверы и пользователей без скрытых привязок; peer-only привязки не считаются всем интерфейсом. Общий кэш обойдён, фоновое enrichment не запускается, topN и порог карты читаются без ключей коллектора. Между чтениями проверяются доступ и источник; перед выдачей повторно сверяются топология и настройки. Лимиты: 20000 строк и 1 МиБ ответа; будущие строки исключены из окна общего map engine. Порог карты задаётся настройками и не переопределяется MCP-запросом.
Карта выводит предположительные связи из retained потоков и текущей топологии. live=false, inferredPathsVerified=false, forwardingVerified=false, graphComplete=false; наличие listener не подтверждает свежесть потоков или доставку. Traceroute и native poll не выполняются. Историческое владение интерфейсами и полное покрытие сети не подтверждаются этой выдачей.
Приёмка карты: настоящий маршрут REST через Fastify.inject и изолированную SQL БД, совпадение totals/services/hops; отдельно проверены скрытые серверы/пользователи/peer/pending, общий кэш со скрытым именем, вложенные страницы, filters/dedup/future/row limit, source ABA, topology/threshold drift и cancel/pause, отсутствие планов. Полная регрессия 27 профилей, SQL logs, настоящий restore/tamper, build и ESLint прошли. CHR forwarding и внешние AI-клиенты остаются отдельными пунктами.
Файлы коллектора NetFlow: подтверждаемый экспорт
mm_netflow_host_files_export_plan (traffic.flow.hostFiles.export, mm:traffic:write) создаёт зашифрованный JSON-пакет через общий REST builder. Требуются global scope, все серверы приложения и человеческое подтверждение. MCP получает metadata/downloadPath/SHA-256; содержимое с приватным ключом не возвращается через MCP и не попадает в аудит. Пакет доступен 15 минут только вошедшему владельцу с правом настройки NetFlow. MCP bearer не заменяет JWT портала.
Подписаны назначение, credential, policy/generation, источник, заголовок, срок и hashes. Источник включает точный набор серверов и сформированные файлы; смена конфигурации или ключа блокирует скачивание. Проверки выполняются до загрузки шифротекста, до расшифровки и перед выдачей. После создания отдельно проверяются сохранённый шифротекст и актуальность источника. Лимиты: 1 МиБ plaintext, 2 МиБ ciphertext и общая квота временных артефактов. Установка и применение файлов не выполняются.
Общий HTTP download теперь проверяет подписанный тип и hashes логовых артефактов: подмена секретного пакета под видом логов не даёт получить ключ через другой канал. Неподписанные старые артефакты требуют повторного формирования.
Приёмка: approval/full scope, owner-only bundle, настоящий JWT HTTP и REST parity, отклонение MCP bearer/no-auth, подмена header/kind/cipher и cross-purpose log HTTP, stale source, idempotency и отзыв после чтения шифротекста. Полный прогон 27 профилей/SQL logs/restore/tamper прошёл до последнего уточнения read-back; финальные целевые SQL/HTTP/restore-сценарии завершились по журналу, отдельный exit code последнего процесса не наблюдался. Финальные build, lint и coverage прошли. Native установка и внешний AI-клиент этим сценарием не принимаются.
Настройка Telegram через MCP
mm_alerts_telegram_update_plan (alerts.telegram.update, mm:alerts:write) принимает строгий непустой набор settings (chatId/messageThreadId) и/или secretRef. Требуются global scope, все серверы приложения и человеческое подтверждение. Новое разрешение существующим подключениям автоматически не выдаётся.
Пропущенные поля сохраняются; messageThreadId=null очищает тему, secretRef=null очищает токен. Для нового токена нужна ссылка на глобальный секрет владельца с purpose alerts-telegram-bot. Сырой token в MCP-запросе не принимается. Токен не возвращается в preview, результате и аудите. Перед подтверждением запечатываются приватный снимок/updatedAt, каталог и ссылка; перед записью повторно проверяются доступ, конфигурация и ссылка на секрет. Общий application lock и guarded selective-update используются также REST: защищённый объект alerts-telegram:1 нельзя изменить в обход плана. Результат подтверждается чтением сохранённых полей.
Настройка сама не отправляет сообщений и не проверяет доступность бота. Обратное изменение требует нового плана; прежний токен после замены не выдаётся. Приёмка: SQL/runtime и REST, preserve/clear/thread, owner/purpose refs, strict input, full scope/human approval, stale source/ref, REST protection, cancel/pause, idempotency и отсутствие токена в preview/audit. Все 27 профилей, SQL logs, real restore/tamper, build/lint прошли. POST тестовой отправки завершён следующим этапом ниже; внешняя Telegram-доставка отдельно не принята.
Этот же полный прогон повторно прошёл финальный verifier шифротекста/источника NetFlow host-files и JWT/cross-purpose HTTP-сценарии. Он дополняет исторический протокол экспорта, где exit code последнего отдельного HTTP-прогона не наблюдался; историческое поле не переписано.
Тестовая отправка Telegram
mm_alerts_telegram_test_plan (alerts.telegram.test, mm:alerts:write) требует full global/server scope и человеческого подтверждения. План показывает адресат, тему и точный текст. Используются сохранённые параметры либо owner/purpose secretRef; сырой token в MCP не принимается. Ссылка использует тот же purpose alerts-telegram-bot. Rule preview и текст ограничены по размеру. Перед отправкой сверяются приватный источник, ссылка и точное совпадение payload с подтверждённым preview.
Общий REST/MCP builder сохраняет fallback параметров и формат сообщения. На попытку выполняется один POST к фиксированному API Telegram, без redirect и автоматического повтора; ответ ограничен 64 КиБ, timeout — 30 секунд. REST также проходит общий guard защищённого test-объекта. Положительный ответ API — только acknowledgement (deliveryVerified=false, verification inconclusive). Явный отрицательный API receipt сохраняет outcome=rejected и partial; потеря, malformed или oversized ответ даёт unknown. Повтор с тем же idempotency key не отправляет снова. Новый тест после unknown может создать дубликат и требует нового человеческого подтверждения.
Настройки и история срабатываний не меняются. Уже отправленный HTTP-запрос нельзя отозвать; пауза блокирует дальнейшие проверки/отправки и может оставить результат неизвестным. Токены и provider error descriptions в результат MCP не передаются.
Приёмка: настоящий локальный HTTP provider и REST payload parity, одно обращение/идемпотентность, ref/override, accepted/rejected/lost/malformed/oversized, source drift после intent до HTTP, защита REST, schema/cancel/pause и отсутствие токена в аудите. Все 27 профилей, SQL logs и real restore/tamper прошли до последней preview-сверки; после неё отдельно прошли финальные SQL/HTTP/restore, build и lint. Несовпадение текста/адресата с preview проверено с нулём отправок. Настоящий Telegram не вызывался; внешняя доставка не принята.
Legacy OSPF: применение модели приложения и отдельное восстановление
mm_ospf_application_optimize_plan принимает serverId и pingWeight (0–100, по умолчанию 60). Использует настоящий общий REST ranker/apply; выбранная модель сохраняет округления, минимумы и fallback. Требуются mm:network:write, допуск ко всему каталогу приложения (не более 10 серверов) и подтверждение человеком даже при autonomous-подключении. В preview показаны конкретные from/to cost; до 50 записей выполняются последовательно. Этот инструмент не заменяет измеряемый optimizer v7 и не подтверждает forwarding, Full/BFD или свежий bandwidth.
План связывает SQL-источники, native OSPF-конфигурацию, opaque поля, подключения/epoch, права и защиты private HMAC. Они проверяются перед PATCH после durable intent и после read-back под application/router locks. Источники или защиты изменились — нужен новый план. Игнорирование PATCH, потеря ответа и посторонние изменения останавливают следующие записи; автоматического повтора нет. Receipt содержит nativeWrites отдельно от числа сервисных шагов и forwardingVerified:false. mm_operation_reconcile выполняет только чтение и может подтвердить исходное, конечное или промежуточное prefix-состояние.
mm_ospf_application_restore_plan принимает operationId завершённой legacy OSPF операции этого подключения и владельца. Это новый человеческий план исходных cost. Он сверяет native-конфигурацию с подтверждённым prefix, а затем запечатывает свежие источники и обратные цели: изменение SQL-метрик и порядка рейтинга не превращает восстановление в повтор оптимизации. Неизвестный результат сначала сверяется без записи; восстановление возможно только при подтверждённом native-prefix. Посторонние изменения конфигурации, новый endpoint/epoch, защиты или утрата допуска блокируют его. Универсальный native recovery для этого сервиса не используется.
SQL/HTTP-проверки, все 27 backend-профилей, SQL logs, настоящий restore/tamper, build/lint прошли. SQL/HTTP-приёмка. После неё новые команды отдельно приняты на обоих CHR в конфигурационном сценарии ниже. Прежняя IPv6 GRE-попытка с результатом 2/3 до OSPF остаётся незакрытой пакетной проверкой.
CHR: legacy apply и отдельный human restore
23 октября оба тестовых CHR прошли реальные mm_ospf_application_optimize_plan и mm_ospf_application_restore_plan: 30/40 → 10/20 → 30/40, восемь cost PATCH суммарно, сверка без дополнительных записей, 32 подтверждённые MCP-операции с учётом создания и очистки стенда. Все 24 исходных fingerprints двух устройств восстановлены, тестовые объекты удалены. Неизменяемый протокол, аудит и source hashes.
Профиль npm --prefix backend run test:mcp:pg -- --chr-ospf-legacy работает только с двумя явными CHR из allowlist, отдельным временным PostgreSQL и приватным вводом пароля в terminal. Используются MMAPP_TEST_CHR_HOSTS, MMAPP_TEST_CHR_USER=admin и при необходимости MMAPP_TEST_CHR_TUNNEL_PORTS. До первой записи требуются пустые исходные OSPF templates и отсутствие соседей. Профиль создаёт только уникальные disabled bridge без портов/адресов, отдельную VRF и passive templates; очистка проверяет точное владение и не повторяет неизвестные записи. Выбор одновременно нескольких CHR-профилей запрещён.
Это приёмка изменения конфигурации. Она не подтверждает Full/BFD, прохождение пакетов, независимый канал или трёхузловый failover и не закрывает прежнюю потерю IPv6 GRE-пакета. Два исторических route hash c74d0d3c остаются неподтверждёнными.
Готовность GRE-стенда перед пакетной OSPF-приёмкой — в работе
Начальный bring-up стенда теперь требует два подряд результата строго 3/3 с полной подтверждённой трассой, максимум за четыре read-only наблюдения. Начальный PING_PARTIAL_LOSS сохраняется как unknown и сбрасывает серию. Полный отказ, другой unknown, неполная трасса, недостоверные counters и ошибка транспорта останавливают запуск сразу. Проверки после fault/recovery и производственный admission пути не смягчались; повторов конфигурационных команд нет.
До/после IPv6-пробы сохраняются только поля адресов собственного GRE и безопасная проекция neighbor cache; отсутствующие flags остаются null. Путь и поля cache сверены с документацией MikroTik IPv6 Neighbor Discovery. Это диагностические наблюдения, не доказательство причины потери пакета.
Модели, build/lint, SQL/HTTP/restore, профиль auth/MCP и SQL logs прошли. Новый реальный запуск d33a0265 остановился раньше readiness: GET /ipv6/address вернул HTTP 401 при подготовке bridge update. Операция отклонена до записи, все 16 исходных fingerprints восстановлены; OSPF cost и readiness-пробы не выполнялись. Позднее восемь последовательных GET с теми же учётными данными вернули 200. Причина 401 не установлена, настройки сервисов/сессий не менялись. Прогресс и границы проверки, сохранённый неуспешный запуск. Историческая потеря IPv6 2/3 также сохранена отдельно. Пакетная приёмка остаётся открытой.
Восстановление GRE из ревизии — локально принято
mm_gre_revision_restore_plan({serverId, revisionId}) восстанавливает весь раздел GRE выбранного сервера через общий с REST исполнитель. Выдаётся отдельное разрешение network.gre.revision.restore; существующим подключениям оно автоматически не добавляется. Даже autonomous-подключение требует человеческого approval. Review показывает удаляемые/восстанавливаемые GRE, адреса, MTU и enabled; PSK и комментарии не выдаются. Пустой или маскированный PSK старой ревизии сохраняет подтверждённый текущий ключ. Явное удаление PSK выполняется отдельным планом изменения GRE.
Все затронутые GRE отключаются до изменения адресов; включение выполняется последним. Используемый туннель не удаляется. Перед каждой командой, после durable intent и после read-back сверяются источники, защиты и вся конфигурация. Потеря ответа, игнорирование или изменение зависимостей останавливают пакет без retry и автоматического отката. Предел — 50 native-команд и 120 секунд выполнения. Receipt отдельно показывает подтверждённые команды и запись rollback-ревизии; IPv6 readiness, IPsec SA и forwarding не подтверждаются.
Для сверки без записи дополнительно выдаются operations.reconcile и mm:network:read, сохраняются допуск к исходной операции и mm:network:write. mm_operation_reconcile сравнивает исходный proof или сохранённый проверенный конечный receipt. Без конечного checkpoint желаемое состояние не объявляется достигнутым. После частичного/неизвестного исхода новое восстановление требует нового человеческого плана.
Проверки: npm --prefix backend run test:mcp:pg -- --gre-revision --restore — отдельный временный PostgreSQL и локальный HTTP-стенд; npm --prefix backend run test:mcp:pg:all -- --restore — общая SQL/HTTP-приёмка и все 27 профилей. Для настоящего dump/restore нужен MMAPP_PG_CLIENT_BIN. Оба прогона, модели, build и ESLint прошли. Протокол. Реальная CHR-приёмка нового адаптера выполнялась, но пока не принята; см. текущий протокол. Актуальный реестр — 328 инструментов, REST 168/62/32 из 262. Полный план остаётся открытым.
Проверка конфигурационной привязки расписаний: npm --prefix backend run test:mcp:telemetry-configuration и npm --prefix backend run test:mcp:telemetry-configuration:pg. Второй профиль создаёт и удаляет собственную локальную PostgreSQL, применяет текущий manifest, выполняет настоящие prepare/approve/apply для Traffic/Uptime/API Ping и проверяет допустимые изменения collector metadata, отказ при изменении настроек и скрытых полей. Профиль запускается отдельно, без --restore и без подключения CHR. Миграцию reserved routing отдельно проверяет npm --prefix backend run test:mcp:routing-schema:pg; она не включает публичный autoRecovery.
Адресный повтор упавшего профиля: npm --prefix backend run test:mcp:pg:all -- --regression-only --profile=test:auth. Режим принимает ровно один известный профиль из test:all, создаёт собственную одноразовую БД и дополнительно проверяет SQL логов. Он явно пропускает основную MCP-интеграцию и terminal restore, не объявляя их повторно принятыми; смешивание с --restore или другим отдельным профилем запрещено.