diff --git a/backend/src/services/mikrotik-response.test.ts b/backend/src/services/mikrotik-response.test.ts index f4e8a634..7da668df 100644 --- a/backend/src/services/mikrotik-response.test.ts +++ b/backend/src/services/mikrotik-response.test.ts @@ -59,3 +59,25 @@ test("RouterOS complete response: success, explicit HTTP rejection and body surv await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())) } }) + +test("RouterOS nonempty malformed JSON cannot confirm PATCH; explicit empty success stays valid", async () => { + const server = createServer((req, res) => { + req.resume() + req.on("end", () => { + res.writeHead(200, { "content-type": "application/json" }) + res.end(req.url?.endsWith("/empty") ? "" : "{broken acknowledgement") + }) + }) + await new Promise(resolve => server.listen(0, "127.0.0.1", resolve)) + const address = server.address() + assert.ok(address && typeof address !== "string") + const client = new MikrotikClient({ host: "127.0.0.1", port: address.port, useSsl: false, verifySsl: false, username: "fixture", password: "fixture" }) + try { + for (const method of ["get", "post", "put", "patch"] as const) { + await assert.rejects(method === "get" ? client.get("/malformed", 500) : client[method]("/malformed", {}, 500), /JSON|подтверждение/) + } + assert.deepEqual(await client.patch("/empty", {}, 500), {}) + } finally { + await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())) + } +}) diff --git a/backend/src/services/mikrotik.ts b/backend/src/services/mikrotik.ts index 9766a4c1..1ab933e5 100644 --- a/backend/src/services/mikrotik.ts +++ b/backend/src/services/mikrotik.ts @@ -375,7 +375,9 @@ function rosPatch( resolve({}) return } - try { resolve(JSON.parse(buf)) } catch { resolve({}) } + try { resolve(JSON.parse(buf)) } catch { + reject(new Error("Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен")) + } }) }) diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 1d3b8ea9..a9ccf3d8 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -1,6 +1,6 @@ # UX/UI: протокол внешней приёмки 12.5 -Актуальное продолжение 2026-10-10: завершены12.5.93–101. Backend ux-response100/frontend ux-a11y101; main1207/1208 исходно, единственный OSPF geometry failure исправлен/delta5/5; context221/221, backend171 node cases, accessibility24 local/20 live passed в точных границах. Старые evidence восстановлены, credentials не менялись. Следующий12.5.102 — malformed nonempty PATCH confirmation не должен приниматься как{}, затем финальный контроль ограничений. Матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. +Актуальное продолжение 2026-10-10: завершены12.5.93–102. Backend ux-patch102/frontend ux-a11y101; malformed nonempty PATCH confirmation больше не становится{}, SDK/native state/cleanup приняты. В ACK fixture обнаружен Ping1/3 наCHR1→2 и3/3 обратно; zero-loss GRE не принят. Следующий12.5.103 — packet rows/public versus own GRE diagnostics, затем оставшиеся network/external границы. Общая main/context и accessibility proofs в99/101, матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. IPsec78: реальный PSK responder established, mode-config198.18.78.10 и online=true подтверждены API; точные собственные объекты удалены. Сертификатный/DN online, late failure и history restore остаются открытыми. [Отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json), [журнал](ux-ui-progress.md). @@ -971,3 +971,15 @@ Scoped TypeScript/новые components+test lint passed; старый NavUser s [Live20/20](ux-ui/acceptance/live-a11y-2026-10-10.json) настоящего frontend/backend безHTTP mocks:5 routes×2 themes×2 widths, axe0/pageerror0/overflow0/API writes0. Сертификатные3 blocks во всех4 combinations доступны Shift+Tab/Tab иArrowRight. [Светлая CLI/фокус320](ux-ui/screens/certificates-a11y-light-320-2026-10-10.png), [тёмные Filters320](ux-ui/screens/filters-a11y-dark-320-2026-10-10.png) просмотрены; остальные dark certificate/light filters snapshots сохранены. Code screenshot показывает горизонтально прокрученный focused block, его содержимое не обрезано в данных. Это scoped accessibility delta, не полная WCAG/все состояния/повтор всегоmain. Два CHR/credentials/configuration не менялись, только3 compose containers/backend/PG healthy. Следующий102 — клиент PATCH сейчас принимает nonempty malformed JSON как{}, что может выглядеть ACK; проверить/исправить его без изменения правила empty successful response, затем ограниченная профильная фиксация. Один локальный коммит без push; этап12.5 остаётся открытым. + +## 12.5.102 — malformed PATCH JSON не подтверждает изменение (2026-10-10) + +Раньше rosPatch превращал непустой невалидный JSON в{} и мог выглядеть успешным ACK. Теперь возвращает error «Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен» без эха тела ответа. Empty2xx compatibility, нормальный JSON, explicit401, команды/права/метаданные/автоматические retries не менялись. [MikroTik REST PATCH](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST%2BAPI) описывает updated object как результат успешного изменения; ошибки не следует заменять пустым объектом. + +[Отчёт](ux-ui/acceptance/patch-acknowledgement-2026-10-10.json): before8 tests/7pass/1fail (PATCH falsely resolved); after8/8. GET/POST/PUT rejection иexplicit empty PATCH сохранены, partial-response6/complete success/401 прежние. IPsec иOSPF optimizer profile suites/локальный backend production build/new test lint passed. Консольные assertion scripts этих suites не переобозначаются произвольным числом node:test cases. Whole backend/main/context не повторялись после одного parser branch; общая100/99 и профили сохраняют свои границы. + +**Native.** Своя GRE pair/private198.18.102.0/30 на двух CHR. Normal PATCH comment вернул actual updated.id/comment. Relay следующего PATCH сначала получил настоящий native200/updated comment, затем отдал downstream malformed JSON200. SDK rejected unknown; независимый GET подтвердил фактически изменённыйcomment. PatchCalls1/noauto retry дляfault path. Это HTTP response fault injection после real write, не реальное повреждение WAN; не заявлена приёмка каждого API mutation handler. До любых writes проверены оба устройства/subnet/отсутствие GRE с такими же outer endpoints. Exact own IDs/name/comment/address/interface cleanup, original3 collections×2 совпали, public/default/metadata/195.195.195.195/32 иcredentials сохранены. + +**Связность/оснастка.** Первый fixture остановился доPATCH на требовании Ping3/3, фактически2/3; cleanup accepted. ACK scenario не требует нулевых потерь: повтор использовал по одному paced Ping3/1s, сохранил фактические1/3/66% наCHR1→2 и3/3/0% обратно; zero-loss GRE не принят. Сетевые потери не скрыты успешным ACK. Следующий103 — read-only native packet rows/public versus own GRE diagnostics, чтобы отличить actual packet loss от неверной интерпретации статистики; BGP hold-timer безBFD отложен до понимания пути. + +**Deployment.** Одна backend Docker production build изresponse100 +client/test, без dependency/миграций; entry/node --check/pg_restore18.6/compose --wait passed. Backend ux-patch102/version1.0.0-test.patch102/image34fca84b8721…; frontend ux-a11y101 прежний. Приватный .env backup, изменён только BACKEND_IMAGE_TAG, labelpatch102 неGitSHA. Только3 compose containers/backend/PG healthy. Один локальный commit без push; этап12.5 открыт. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 56917efa..777541f7 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-10: завершены12.5.93–101. Backend ux-response100/frontend ux-a11y101; main1207/1208 исходно, единственный OSPF geometry failure исправлен/delta5/5; context221/221, backend171 node cases, accessibility24 local/20 live passed в точных границах. Старые evidence восстановлены, credentials не менялись. Следующий12.5.102 — malformed nonempty PATCH confirmation не должен приниматься как{}, затем финальный контроль ограничений. Матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. +Актуальное продолжение 2026-10-10: завершены12.5.93–102. Backend ux-patch102/frontend ux-a11y101; malformed nonempty PATCH confirmation больше не становится{}, SDK/native state/cleanup приняты. В ACK fixture обнаружен Ping1/3 наCHR1→2 и3/3 обратно; zero-loss GRE не принят. Следующий12.5.103 — packet rows/public versus own GRE diagnostics, затем оставшиеся network/external границы. Общая main/context и accessibility proofs в99/101, матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-10. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-10 -Актуальное продолжение 2026-10-10: завершены12.5.93–101. Backend ux-response100/frontend ux-a11y101; main1207/1208 исходно, единственный OSPF geometry failure исправлен/delta5/5; context221/221, backend171 node cases, accessibility24 local/20 live passed в точных границах. Старые evidence восстановлены, credentials не менялись. Следующий12.5.102 — malformed nonempty PATCH confirmation не должен приниматься как{}, затем финальный контроль ограничений. Матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. +Актуальное продолжение 2026-10-10: завершены12.5.93–102. Backend ux-patch102/frontend ux-a11y101; malformed nonempty PATCH confirmation больше не становится{}, SDK/native state/cleanup приняты. В ACK fixture обнаружен Ping1/3 наCHR1→2 и3/3 обратно; zero-loss GRE не принят. Следующий12.5.103 — packet rows/public versus own GRE diagnostics, затем оставшиеся network/external границы. Общая main/context и accessibility proofs в99/101, матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. Этапы0–11 завершены в локальных границах журнала. История выполненных внешних блоков и доказательства сохранены в [журнале](ux-ui-stage-12.md) и [протоколе](ux-ui-external-acceptance.md). Реальная Telegram доставка, Portal SSO, multi-instance и оставшиеся профильные сетевые ограничения открыты. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 7efb1e9d..2eaa2034 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-10: завершены12.5.93–101. Backend ux-response100/frontend ux-a11y101; main1207/1208 исходно, единственный OSPF geometry failure исправлен/delta5/5; context221/221, backend171 node cases, accessibility24 local/20 live passed в точных границах. Старые evidence восстановлены, credentials не менялись. Следующий12.5.102 — malformed nonempty PATCH confirmation не должен приниматься как{}, затем финальный контроль ограничений. Матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. +Актуальное продолжение 2026-10-10: завершены12.5.93–102. Backend ux-patch102/frontend ux-a11y101; malformed nonempty PATCH confirmation больше не становится{}, SDK/native state/cleanup приняты. В ACK fixture обнаружен Ping1/3 наCHR1→2 и3/3 обратно; zero-loss GRE не принят. Следующий12.5.103 — packet rows/public versus own GRE diagnostics, затем оставшиеся network/external границы. Общая main/context и accessibility proofs в99/101, матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -36,7 +36,19 @@ | 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 | | 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 | | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | -| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–101 и ограничения ниже. Runtime backend ux-diagnostics89/frontend ux-ospf91. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–102 и ограничения ниже. Runtime backend ux-diagnostics89/frontend ux-ospf91. | + +## 12.5.102 — malformed PATCH JSON не подтверждает изменение (2026-10-10) + +Раньше rosPatch превращал непустой невалидный JSON в{} и мог выглядеть успешным ACK. Теперь возвращает error «Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен» без эха тела ответа. Empty2xx compatibility, нормальный JSON, explicit401, команды/права/метаданные/автоматические retries не менялись. [MikroTik REST PATCH](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST%2BAPI) описывает updated object как результат успешного изменения; ошибки не следует заменять пустым объектом. + +[Отчёт](ux-ui/acceptance/patch-acknowledgement-2026-10-10.json): before8 tests/7pass/1fail (PATCH falsely resolved); after8/8. GET/POST/PUT rejection иexplicit empty PATCH сохранены, partial-response6/complete success/401 прежние. IPsec иOSPF optimizer profile suites/локальный backend production build/new test lint passed. Консольные assertion scripts этих suites не переобозначаются произвольным числом node:test cases. Whole backend/main/context не повторялись после одного parser branch; общая100/99 и профили сохраняют свои границы. + +**Native.** Своя GRE pair/private198.18.102.0/30 на двух CHR. Normal PATCH comment вернул actual updated.id/comment. Relay следующего PATCH сначала получил настоящий native200/updated comment, затем отдал downstream malformed JSON200. SDK rejected unknown; независимый GET подтвердил фактически изменённыйcomment. PatchCalls1/noauto retry дляfault path. Это HTTP response fault injection после real write, не реальное повреждение WAN; не заявлена приёмка каждого API mutation handler. До любых writes проверены оба устройства/subnet/отсутствие GRE с такими же outer endpoints. Exact own IDs/name/comment/address/interface cleanup, original3 collections×2 совпали, public/default/metadata/195.195.195.195/32 иcredentials сохранены. + +**Связность/оснастка.** Первый fixture остановился доPATCH на требовании Ping3/3, фактически2/3; cleanup accepted. ACK scenario не требует нулевых потерь: повтор использовал по одному paced Ping3/1s, сохранил фактические1/3/66% наCHR1→2 и3/3/0% обратно; zero-loss GRE не принят. Сетевые потери не скрыты успешным ACK. Следующий103 — read-only native packet rows/public versus own GRE diagnostics, чтобы отличить actual packet loss от неверной интерпретации статистики; BGP hold-timer безBFD отложен до понимания пути. + +**Deployment.** Одна backend Docker production build изresponse100 +client/test, без dependency/миграций; entry/node --check/pg_restore18.6/compose --wait passed. Backend ux-patch102/version1.0.0-test.patch102/image34fca84b8721…; frontend ux-a11y101 прежний. Приватный .env backup, изменён только BACKEND_IMAGE_TAG, labelpatch102 неGitSHA. Только3 compose containers/backend/PG healthy. Один локальный commit без push; этап12.5 открыт. ## 12.5.101 — доступность общей оболочки, текста и OSPF-колонки (2026-10-10) diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index cb6e53e3..f8dd5535 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,8 +1,8 @@ # Оставшаяся внешняя приёмка — 2026-10-10 -Это актуальная матрица после 12.5.101. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.102. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-response100`, frontend `ux-a11y101`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты последнего сценария удалены, исходные11 коллекций×2 восстановлены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-patch102`, frontend `ux-a11y101`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты последнего сценария удалены, исходные11 коллекций×2 восстановлены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | @@ -25,7 +25,7 @@ ## Следующая последовательность 1. **12.5.95 завершён:** [source/context/compiled audit](ux-ui/acceptance/deployment-source-audit-2026-10-10.json), production source drift не выявлен; нормализация и исключения явно указаны. -2. **12.5.96 timezone завершён:** [6 live UI cases](ux-ui/acceptance/browser-speed-timezone-2026-10-10.json). 97 HTTP receipt disconnect принят: [протокол](ux-ui/acceptance/speed-disconnect-2026-10-10.json). 98 сообщение неизвестного native результата исправлено/развёрнуто. 99 main/context завершён с точной записью одного failure/delta;100 transport и101 accessibility исправлены/развёрнуты.102 — nonempty malformed PATCH confirmation. +2. **12.5.96 timezone завершён:** [6 live UI cases](ux-ui/acceptance/browser-speed-timezone-2026-10-10.json). 97 HTTP receipt disconnect принят: [протокол](ux-ui/acceptance/speed-disconnect-2026-10-10.json). 98 сообщение неизвестного native результата исправлено/развёрнуто. 99 main/context завершён с точной записью одного failure/delta;100 transport и101 accessibility исправлены/развёрнуты.102 malformed PATCH исправлен/принят.103 — диагностика наблюдённых GRE потерь; hold-timer безBFD пока не принят. 3. **Заключительный профильный контроль:** после последнего исправления собрать только затронутую часть, проверить её live и обновить матрицу. Общую регрессию выполнить один раз на согласованном runtime. 4. **Внешние зависимости:** Telegram/Portal/client OS/multi-WAN/scale проходят отдельную приёмку при наличии нужных аккаунтов, устройств и разрешений. Лабораторный результат двух CHR не закрывает их автоматически. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 44a0877e..30552790 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -2276,3 +2276,15 @@ Scoped TypeScript/новые components+test lint passed; старый NavUser s [Live20/20](ux-ui/acceptance/live-a11y-2026-10-10.json) настоящего frontend/backend безHTTP mocks:5 routes×2 themes×2 widths, axe0/pageerror0/overflow0/API writes0. Сертификатные3 blocks во всех4 combinations доступны Shift+Tab/Tab иArrowRight. [Светлая CLI/фокус320](ux-ui/screens/certificates-a11y-light-320-2026-10-10.png), [тёмные Filters320](ux-ui/screens/filters-a11y-dark-320-2026-10-10.png) просмотрены; остальные dark certificate/light filters snapshots сохранены. Code screenshot показывает горизонтально прокрученный focused block, его содержимое не обрезано в данных. Это scoped accessibility delta, не полная WCAG/все состояния/повтор всегоmain. Два CHR/credentials/configuration не менялись, только3 compose containers/backend/PG healthy. Следующий102 — клиент PATCH сейчас принимает nonempty malformed JSON как{}, что может выглядеть ACK; проверить/исправить его без изменения правила empty successful response, затем ограниченная профильная фиксация. Один локальный коммит без push; этап12.5 остаётся открытым. + +## 12.5.102 — malformed PATCH JSON не подтверждает изменение (2026-10-10) + +Раньше rosPatch превращал непустой невалидный JSON в{} и мог выглядеть успешным ACK. Теперь возвращает error «Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен» без эха тела ответа. Empty2xx compatibility, нормальный JSON, explicit401, команды/права/метаданные/автоматические retries не менялись. [MikroTik REST PATCH](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST%2BAPI) описывает updated object как результат успешного изменения; ошибки не следует заменять пустым объектом. + +[Отчёт](ux-ui/acceptance/patch-acknowledgement-2026-10-10.json): before8 tests/7pass/1fail (PATCH falsely resolved); after8/8. GET/POST/PUT rejection иexplicit empty PATCH сохранены, partial-response6/complete success/401 прежние. IPsec иOSPF optimizer profile suites/локальный backend production build/new test lint passed. Консольные assertion scripts этих suites не переобозначаются произвольным числом node:test cases. Whole backend/main/context не повторялись после одного parser branch; общая100/99 и профили сохраняют свои границы. + +**Native.** Своя GRE pair/private198.18.102.0/30 на двух CHR. Normal PATCH comment вернул actual updated.id/comment. Relay следующего PATCH сначала получил настоящий native200/updated comment, затем отдал downstream malformed JSON200. SDK rejected unknown; независимый GET подтвердил фактически изменённыйcomment. PatchCalls1/noauto retry дляfault path. Это HTTP response fault injection после real write, не реальное повреждение WAN; не заявлена приёмка каждого API mutation handler. До любых writes проверены оба устройства/subnet/отсутствие GRE с такими же outer endpoints. Exact own IDs/name/comment/address/interface cleanup, original3 collections×2 совпали, public/default/metadata/195.195.195.195/32 иcredentials сохранены. + +**Связность/оснастка.** Первый fixture остановился доPATCH на требовании Ping3/3, фактически2/3; cleanup accepted. ACK scenario не требует нулевых потерь: повтор использовал по одному paced Ping3/1s, сохранил фактические1/3/66% наCHR1→2 и3/3/0% обратно; zero-loss GRE не принят. Сетевые потери не скрыты успешным ACK. Следующий103 — read-only native packet rows/public versus own GRE diagnostics, чтобы отличить actual packet loss от неверной интерпретации статистики; BGP hold-timer безBFD отложен до понимания пути. + +**Deployment.** Одна backend Docker production build изresponse100 +client/test, без dependency/миграций; entry/node --check/pg_restore18.6/compose --wait passed. Backend ux-patch102/version1.0.0-test.patch102/image34fca84b8721…; frontend ux-a11y101 прежний. Приватный .env backup, изменён только BACKEND_IMAGE_TAG, labelpatch102 неGitSHA. Только3 compose containers/backend/PG healthy. Один локальный commit без push; этап12.5 открыт. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index d7a9ac9b..82c615e2 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-10 -Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-response100/version1.0.0-test.response100, frontend ux-a11y101/version1.0.0-test.a11y101; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. +Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-patch102/version1.0.0-test.patch102, frontend ux-a11y101/version1.0.0-test.a11y101; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. | Параметр | Проверенное состояние | | --- | --- | @@ -14,7 +14,7 @@ | PostgreSQL | postgres:18-alpine,18.6;mmapp-test-postgres healthy;SELECT version() passed | | Данные | Отдельный Compose project mmapp-test,том mmapp-test_mmapp-pgdata и каталог ./data | | Доступ | PostgreSQL не публикуется;frontend3000/backend8000 привязаны к127.0.0.1 после запуска | -| Образы приложения | mmapp-test/backend:ux-response100 и mmapp-test/frontend:ux-a11y101; запущены | +| Образы приложения | mmapp-test/backend:ux-patch102 и mmapp-test/frontend:ux-a11y101; запущены | Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example). @@ -787,3 +787,15 @@ Scoped TypeScript/новые components+test lint passed; старый NavUser s [Live20/20](ux-ui/acceptance/live-a11y-2026-10-10.json) настоящего frontend/backend безHTTP mocks:5 routes×2 themes×2 widths, axe0/pageerror0/overflow0/API writes0. Сертификатные3 blocks во всех4 combinations доступны Shift+Tab/Tab иArrowRight. [Светлая CLI/фокус320](ux-ui/screens/certificates-a11y-light-320-2026-10-10.png), [тёмные Filters320](ux-ui/screens/filters-a11y-dark-320-2026-10-10.png) просмотрены; остальные dark certificate/light filters snapshots сохранены. Code screenshot показывает горизонтально прокрученный focused block, его содержимое не обрезано в данных. Это scoped accessibility delta, не полная WCAG/все состояния/повтор всегоmain. Два CHR/credentials/configuration не менялись, только3 compose containers/backend/PG healthy. Следующий102 — клиент PATCH сейчас принимает nonempty malformed JSON как{}, что может выглядеть ACK; проверить/исправить его без изменения правила empty successful response, затем ограниченная профильная фиксация. Один локальный коммит без push; этап12.5 остаётся открытым. + +## 12.5.102 — malformed PATCH JSON не подтверждает изменение (2026-10-10) + +Раньше rosPatch превращал непустой невалидный JSON в{} и мог выглядеть успешным ACK. Теперь возвращает error «Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен» без эха тела ответа. Empty2xx compatibility, нормальный JSON, explicit401, команды/права/метаданные/автоматические retries не менялись. [MikroTik REST PATCH](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST%2BAPI) описывает updated object как результат успешного изменения; ошибки не следует заменять пустым объектом. + +[Отчёт](ux-ui/acceptance/patch-acknowledgement-2026-10-10.json): before8 tests/7pass/1fail (PATCH falsely resolved); after8/8. GET/POST/PUT rejection иexplicit empty PATCH сохранены, partial-response6/complete success/401 прежние. IPsec иOSPF optimizer profile suites/локальный backend production build/new test lint passed. Консольные assertion scripts этих suites не переобозначаются произвольным числом node:test cases. Whole backend/main/context не повторялись после одного parser branch; общая100/99 и профили сохраняют свои границы. + +**Native.** Своя GRE pair/private198.18.102.0/30 на двух CHR. Normal PATCH comment вернул actual updated.id/comment. Relay следующего PATCH сначала получил настоящий native200/updated comment, затем отдал downstream malformed JSON200. SDK rejected unknown; независимый GET подтвердил фактически изменённыйcomment. PatchCalls1/noauto retry дляfault path. Это HTTP response fault injection после real write, не реальное повреждение WAN; не заявлена приёмка каждого API mutation handler. До любых writes проверены оба устройства/subnet/отсутствие GRE с такими же outer endpoints. Exact own IDs/name/comment/address/interface cleanup, original3 collections×2 совпали, public/default/metadata/195.195.195.195/32 иcredentials сохранены. + +**Связность/оснастка.** Первый fixture остановился доPATCH на требовании Ping3/3, фактически2/3; cleanup accepted. ACK scenario не требует нулевых потерь: повтор использовал по одному paced Ping3/1s, сохранил фактические1/3/66% наCHR1→2 и3/3/0% обратно; zero-loss GRE не принят. Сетевые потери не скрыты успешным ACK. Следующий103 — read-only native packet rows/public versus own GRE diagnostics, чтобы отличить actual packet loss от неверной интерпретации статистики; BGP hold-timer безBFD отложен до понимания пути. + +**Deployment.** Одна backend Docker production build изresponse100 +client/test, без dependency/миграций; entry/node --check/pg_restore18.6/compose --wait passed. Backend ux-patch102/version1.0.0-test.patch102/image34fca84b8721…; frontend ux-a11y101 прежний. Приватный .env backup, изменён только BACKEND_IMAGE_TAG, labelpatch102 неGitSHA. Только3 compose containers/backend/PG healthy. Один локальный commit без push; этап12.5 открыт. diff --git a/docs/ux-ui/acceptance/patch-acknowledgement-2026-10-10.json b/docs/ux-ui/acceptance/patch-acknowledgement-2026-10-10.json new file mode 100644 index 00000000..3944ed47 --- /dev/null +++ b/docs/ux-ui/acceptance/patch-acknowledgement-2026-10-10.json @@ -0,0 +1,108 @@ +{ + "date": "2026-10-10", + "name": "mm-ack102-1791576654952", + "devices": [ + { + "serverId": 1, + "sent": 3, + "received": 1, + "packetLoss": "66" + }, + { + "serverId": 2, + "sent": 3, + "received": 3, + "packetLoss": "0" + } + ], + "cleanup": [ + { + "serverId": 1, + "/interface/gre": true, + "/ip/address": true, + "/ip/route": true + }, + { + "serverId": 2, + "/interface/gre": true, + "/ip/address": true, + "/ip/route": true + } + ], + "responseFaultInjected": true, + "routerOsMocks": false, + "normalAck": { + "id": "*6D", + "name": "mm-ack102-1791576654952", + "comment": "mm-ack102-1791576654952-normal" + }, + "independentNativeAck": { + "id": "*6D", + "comment": "mm-ack102-1791576654952-changed", + "httpStatus": 200 + }, + "clientError": "Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен", + "afterIndependentRead": { + "id": "*6D", + "name": "mm-ack102-1791576654952", + "comment": "mm-ack102-1791576654952-changed" + }, + "patchCalls": 1, + "automaticRetry": false, + "preliminary": { + "date": "2026-10-10", + "name": "mm-ack102-1791576431500", + "devices": [], + "cleanup": [ + { + "serverId": 1, + "/interface/gre": true, + "/ip/address": true, + "/ip/route": true + }, + { + "serverId": 2, + "/interface/gre": true, + "/ip/address": true, + "/ip/route": true + } + ], + "responseFaultInjected": true, + "routerOsMocks": false, + "error": "Expected values to be strictly equal:\n\n2 !== 3\n", + "explanation": "Fixture stopped before PATCH checks on unrelated zero-loss Ping criterion; expected3/received2. Own GRE/IP/routes restored." + }, + "runtime": { + "backend": "ux-patch102", + "version": "1.0.0-test.patch102", + "imageId": "sha256:34fca84b8721ff4b83501acea24f18195ae000b788a15f835da4d056b2079777f", + "frontend": "ux-a11y101" + }, + "validation": { + "localTransportBefore": { + "tests": 8, + "passed": 7, + "failed": 1 + }, + "localTransportAfter": { + "tests": 8, + "passed": 8, + "failed": 0 + }, + "ipsecProfile": true, + "ospfOptimizerProfile": true, + "localBackendBuild": true, + "newTestLint": true, + "dockerProductionBuild": true, + "entryCheck": true, + "composeHealthy": true, + "archiveSha256": "c7104b9b711865999256f35d5412406967f3b7da0d144e13f125189a77dfa642", + "source": "response100 context +2 working-tree files; patch102 label not Git SHA" + }, + "limits": [ + "Synthetic malformed downstream response after genuine native PATCH; no physical WAN corruption claim", + "Explicit empty successful response remains compatible; nonempty malformed JSON no longer becomes{}", + "SDK rejection/native state verified; every application mutation handler not repeated", + "GRE steady zero loss not accepted: observed1/3 source1→2,3/3 reverse in accepted ACK fixture; needs diagnostic follow-up" + ] +}