fix(api): завершать запрос при обрыве ответа RouterOS
This commit is contained in:
1 parent
5944e5e751
commit
7f0c2aad0f
13 files changed
+1005
-31
No files matched your search
@@ -25,7 +25,7 @@
|
||||
"test:pg": "tsx src/db/sql-bind.test.ts && tsx src/db/sqlite-json.test.ts && tsx src/db/traffic-flags.test.ts && tsx src/db/pg-schema.test.ts && tsx src/services/config-revisions.test.ts",
|
||||
"test:recursive-routes": "tsx src/routes/recursive-routes.test.ts && tsx src/services/recursive-route-catalog.test.ts && tsx src/services/recursive-apply.test.ts",
|
||||
"test:config-sync": "tsx src/services/config-apply-plan.test.ts && tsx src/services/entity-snapshots.test.ts",
|
||||
"test:ros-file": "tsx src/services/ros-file-contents.test.ts",
|
||||
"test:ros-file": "tsx src/services/ros-file-contents.test.ts && tsx src/services/mikrotik-response.test.ts",
|
||||
"test:scheduler": "tsx src/services/scheduler-running.test.ts && tsx src/services/scheduler-recorded-run.test.ts && tsx src/routes/scheduler.test.ts",
|
||||
"test:backups": "tsx src/services/backup-scheduler-run.test.ts && tsx src/services/backup-restore.test.ts && tsx src/services/backup-deletion.test.ts && tsx src/services/backup-dto.test.ts && tsx src/services/backup-storage-update.test.ts && tsx src/services/backup-job-execution.test.ts && tsx src/routes/backups-operations.test.ts && tsx src/services/s3-backup-client.test.ts",
|
||||
"test:ipsec": "tsx src/services/ipsec-config.test.ts && tsx src/services/ipsec-state.test.ts && tsx src/routes/ipsec-history.test.ts && tsx src/services/ipsec-restore.test.ts && tsx src/services/ipsec-operation.test.ts && tsx src/routes/ipsec-mutation.test.ts && tsx src/routes/ipsec-nat.test.ts && tsx src/routes/ipsec-group.test.ts",
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { test } from "node:test"
|
||||
import assert from "node:assert/strict"
|
||||
import { createServer } from "node:http"
|
||||
import { MikrotikClient } from "./mikrotik.js"
|
||||
|
||||
const methods = ["get", "post", "put", "patch", "delete", "file"] as const
|
||||
for (const method of methods) {
|
||||
test(`RouterOS ${method}: interrupted response rejects promptly without a successful receipt`, async () => {
|
||||
let requests = 0
|
||||
const server = createServer((req, res) => {
|
||||
req.resume()
|
||||
req.on("end", () => {
|
||||
requests++
|
||||
res.writeHead(200, { "content-type": "application/json", "content-length": "1000" })
|
||||
res.write('[{"status":')
|
||||
setTimeout(() => res.destroy(), 20)
|
||||
})
|
||||
})
|
||||
await new Promise<void>(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" })
|
||||
let deadline: ReturnType<typeof setTimeout> | undefined
|
||||
try {
|
||||
const operation = method === "file" ? client.downloadFile({ id: "*A", name: "", size: 8 }, 500)
|
||||
: method === "get" || method === "delete" ? client[method]("/fixture", 500)
|
||||
: client[method]("/fixture", {}, 500)
|
||||
await assert.rejects(Promise.race([operation, new Promise<never>((_, reject) => {
|
||||
deadline = setTimeout(() => reject(Error("Request did not settle after interrupted response")), 1200)
|
||||
})]), /ECONNRESET/)
|
||||
assert.equal(requests, method === "file" ? 2 : 1, "Writes must not retry; file reads keep two existing compatibility strategies")
|
||||
} finally {
|
||||
clearTimeout(deadline)
|
||||
await new Promise<void>((resolve, reject) => server.close(error => error ? reject(error) : resolve()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
test("RouterOS complete response: success, explicit HTTP rejection and body survive", async () => {
|
||||
const server = createServer((req, res) => {
|
||||
req.resume()
|
||||
req.on("end", () => {
|
||||
res.writeHead(req.url?.endsWith("/denied") ? 401 : 200, { "content-type": "application/json" })
|
||||
res.end(req.url?.endsWith("/denied") ? '{"message":"Unauthorized"}' : '{"ack":"confirmed"}')
|
||||
})
|
||||
})
|
||||
await new Promise<void>(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) {
|
||||
assert.deepEqual(await (method === "get" ? client.get("/fixture", 500) : client[method]("/fixture", {}, 500)), { ack: "confirmed" })
|
||||
await assert.rejects(method === "get" ? client.get("/denied", 500) : client[method]("/denied", {}, 500), /401.*Unauthorized/)
|
||||
}
|
||||
await client.delete("/fixture", 500)
|
||||
await assert.rejects(client.delete("/denied", 500), /401.*Unauthorized/)
|
||||
} finally {
|
||||
await new Promise<void>((resolve, reject) => server.close(error => error ? reject(error) : resolve()))
|
||||
}
|
||||
})
|
||||
@@ -15,6 +15,12 @@ import type {
|
||||
|
||||
const MAX_ROS_BODY_BYTES = 8 * 1024 * 1024
|
||||
|
||||
function watchRosResponseFailure(res: http.IncomingMessage, reject: (error: Error) => void): void {
|
||||
res.once("aborted", () => reject(new Error("RouterOS response interrupted (ECONNRESET)")))
|
||||
// IncomingMessage errors are separate from ClientRequest errors after headers arrive.
|
||||
res.once("error", reject)
|
||||
}
|
||||
|
||||
function appendRosBody(body: string, chunk: string, req?: http.ClientRequest): string {
|
||||
if (body.length + chunk.length > MAX_ROS_BODY_BYTES) {
|
||||
req?.destroy(new Error("RouterOS: ответ больше 8 МиБ"))
|
||||
@@ -62,6 +68,7 @@ function rosRequest(
|
||||
}, timeoutMs)
|
||||
|
||||
const req = lib.request(options, (res) => {
|
||||
watchRosResponseFailure(res, error => { clearTimeout(timer); reject(error) })
|
||||
let body = ""
|
||||
res.setEncoding("utf8")
|
||||
res.on("data", (chunk: string) => { body = appendRosBody(body, chunk, req) })
|
||||
@@ -145,6 +152,7 @@ function rosPost(
|
||||
externalSignal?.addEventListener("abort", onExternalAbort)
|
||||
|
||||
req = lib.request(options, (res) => {
|
||||
watchRosResponseFailure(res, error => settle(() => reject(error)))
|
||||
let buf = ""
|
||||
res.setEncoding("utf8")
|
||||
res.on("data", (chunk: string) => { buf = appendRosBody(buf, chunk, req) })
|
||||
@@ -199,6 +207,7 @@ function rosPut(
|
||||
}, timeoutMs)
|
||||
|
||||
const req = lib.request(options, (res) => {
|
||||
watchRosResponseFailure(res, error => { clearTimeout(timer); reject(error) })
|
||||
let buf = ""
|
||||
res.setEncoding("utf8")
|
||||
res.on("data", (chunk: string) => { buf = appendRosBody(buf, chunk, req) })
|
||||
@@ -249,6 +258,7 @@ function rosDelete(
|
||||
}, timeoutMs)
|
||||
|
||||
const req = lib.request(options, (res) => {
|
||||
watchRosResponseFailure(res, error => { clearTimeout(timer); reject(error) })
|
||||
let body = ""
|
||||
res.setEncoding("utf8")
|
||||
res.on("data", (chunk: string) => { body = appendRosBody(body, chunk, req) })
|
||||
@@ -296,6 +306,7 @@ function rosRawRequest(
|
||||
const lib = params.useSsl ? https : http
|
||||
|
||||
const req = lib.request(options, (res) => {
|
||||
watchRosResponseFailure(res, error => { clearTimeout(timer); reject(error) })
|
||||
const chunks: Buffer[] = []
|
||||
res.on("data", (chunk: Buffer) => { chunks.push(chunk) })
|
||||
res.on("end", () => {
|
||||
@@ -351,6 +362,7 @@ function rosPatch(
|
||||
}, timeoutMs)
|
||||
|
||||
const req = lib.request(options, (res) => {
|
||||
watchRosResponseFailure(res, error => { clearTimeout(timer); reject(error) })
|
||||
let buf = ""
|
||||
res.setEncoding("utf8")
|
||||
res.on("data", (chunk: string) => { buf = appendRosBody(buf, chunk, req) })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# UX/UI: протокол внешней приёмки 12.5
|
||||
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98. На стенде backend ux-speed98/frontend ux-ospf91; неизвестный native результат при transport loss теперь явно объяснён одинаково в API/history/UI, live2/2. Собственные fixtures очищены, credentials не менялись. Следующий12.5.99 — общая backend/main/context регрессия; backend/main уже запущены и пока не объявлены прошедшими. Актуальная внешняя матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт.
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98 и100;99 general main UI regression в работе. Backend ux-response100/frontend ux-ospf91: partial RouterOS response теперь prompt ECONNRESET/unknown receipt,7/7 transport и общая backend регрессия24 groups/171 node cases passed, live2/2/cleanup. 30-route live обзор нашёл нарушения контраста/keyboard;101 исправить после main99, затем context. Актуальная матрица 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).
|
||||
|
||||
@@ -138,10 +138,6 @@ BGP-prefix evaluator, отдельное live GRE расписание и recove
|
||||
|
||||
12.5.21: отдельная строка unknown/runId, сохранение snapshot и сверка по идентификатору при чтении истории. 13 браузерных тестов с HTTP-моками/typecheck/ESLint прошли; это не приёмка real browser/PG. Основной backend4c12c55/frontend673e5ba прежний. Следующий 12.5.22 — сборка и проверка обновлённых образов. Полный 12.5 открыт.
|
||||
|
||||
## Локальный unknown UX — 2026-10-08
|
||||
|
||||
12.5.21: отдельная строка unknown/runId, сохранение snapshot и сверка по идентификатору при чтении истории. 13 браузерных тестов с HTTP-моками/typecheck/ESLint прошли; это не приёмка real browser/PG. Основной backend4c12c55/frontend673e5ba прежний. Следующий 12.5.22 — сборка и проверка обновлённых образов. Полный 12.5 открыт.
|
||||
|
||||
## Real browser unknown и deployment — 2026-10-08
|
||||
|
||||
12.5.22: [real browser speed unknown](ux-ui/acceptance/browser-speed-unknown-2026-10-08.json) подтвердил snapshot42, видимый unknown/runId, reconciliation к SQL history done, снятие предупреждения, native1/POST1/JS0/320fits. HTTP/RouterOS-моков нет; COMMIT acknowledgement fault введён на node-pg boundary, физический network disconnect не проверен. [Оба образа8782054 развёрнуты](ux-ui/acceptance/deployed-8782054-2026-10-08.json), [пять экранов](ux-ui/acceptance/deploy-browser-8782054-2026-10-08.json) прошли. Основная БД не восстанавливалась, контроль сохранён. Следующий12.5.23 — ROS-8/9: preflight/late-context changes на реальном PG/native. Полный12.5 открыт.
|
||||
@@ -935,3 +931,21 @@ API502, history error/TXRX/Pingnull, probe error с прежними42/17/15/0;
|
||||
[Native/API/PG](ux-ui/acceptance/speed-message-2026-10-10.json) и [browser](ux-ui/acceptance/browser-speed-message-2026-10-10.json): повторён только изменённый receipt path, одна capped10Mbit/s TCP3s команда, реальное закрытие socket после передачи, native independently done, API/history содержат новое сообщение; прежние синтетические42/17/15/0 сохранены, native1/noauto retry. Live1280/3202/2, сообщение видно в probe card, reload/document fits/pageerror0/UI command POST0. Свои disabled probe/history удалены, исходные IDs совпали, только3 compose containers/backend/PG healthy; RouterOS/credentials не менялись.
|
||||
|
||||
При согласовании указателей94–97 обнаружено, что массовая замена также затронула исторический абзац77 в плане/протоколе. Восстановлен точный абзац из40f730b, история/дата2026-10-09 сохранены; следующие обновления ограничены текущими указателями. Следующий99 — одна общая backend/main/context регрессия на текущем source, с восстановлением исходных доказательств, затем итоговая сводка. General backend/main runs уже запущены, их результат этим блоком не заявлен. Квота23% использовано; этап12.5 открыт. Один локальный commit без push.
|
||||
|
||||
## 12.5.99 — общая регрессия и live обзор (2026-10-10)
|
||||
|
||||
**В работе.** Backend98 npm test24 groups/164 node:test cases/exit0 прошёл с недоступным fixture DB URL; это не real-PG приёмка. Main UI regression запущена на3100 с BACKEND_INTERNAL_URL=http://127.0.0.1:1, API responses контролируются test fixtures. JSON reporter выдаёт итог после завершения; main/context пока не объявлены прошедшими. UI production source не меняется во время main run.493 исходных evidence files защищены snapshot, включая чужие изменённые GRE/VXLAN screenshots; восстановление — после main/context.
|
||||
|
||||
[Live обзор](ux-ui/acceptance/live-shell-a11y-2026-10-10.json):30 routes×1280/320=60, HTTP200/route errors0/pageerror0/document overflow0. Два автоматических read-only OSPF preview POST, apply/mutations0. Default dark theme/scoped axe выявил10 нарушений: alerts empty text, certificate badge/pre keyboard, containers hint, uptime hint; filters320 contrast не воспроизвёлся в устойчивом900ms повторе. Дополнительная светлая тема выявила sidebar subtitles и HR badge. Полная WCAG/все интеграции этим обзором не приняты; исправление101 после завершения main run.
|
||||
|
||||
Согласованность журналов: у всех numbered records есть даты, найден и удалён один точный дубликат12.5.21 изprogress/stage12/external; первая запись и дата2026-10-08 сохранены. Другие исторические данные не удалялись. В процессе внешнего HTTP контроля выявлен общий partial-response hang; исправление и отдельная фиксация100 ниже. Следующий шаг99 — дождаться main result, затем context; не перезапускать уже успешные unchanged suites.
|
||||
|
||||
## 12.5.100 — RouterOS: обрыв тела HTTP ответа больше не зависает (2026-10-10)
|
||||
|
||||
У ClientRequest и IncomingMessage разные error events. После получения headers частичный ответ не вызывал request error/end; запрос оставался pending даже после500ms timeout. Изолированная проверка воспроизвела6 failures по deadline1200ms для GET/POST/PUT/PATCH/DELETE/raw file reading; полныйsuccess/401 проходил. Добавлен общий watchRosResponseFailure на aborted/error во всех6 paths, очистка timer и существующий settle/AbortSignal cleanup дляPOST. Partial response отклоняется как ECONNRESET, без выдуманного ACK и повторных writes. Две прежние read-only file compatibility стратегии сохранены.
|
||||
|
||||
[Протокол](ux-ui/acceptance/routeros-response-transport-2026-10-10.json): после изменения7/7 включая complete success/401, probes.cancel/actual HTTP AbortSignal и byte file parser passed. Тест включён в test:ros-file. Локальный production build, новый test ESLint и Docker build прошли. Исходные2 prefer-const errors mikrotik.ts сохраняются, новые ошибки не добавлены; whole-file lint clean не заявлен. Общая backend регрессия повторена именно из-за изменения общей основы:24 npm groups/171 node:test cases/exit0. Console assertion scripts дополнительно входят в npm suite,171 не заявляется числом всех их assertions.
|
||||
|
||||
**Live.** [Native/API/PG](ux-ui/acceptance/speed-response-body-2026-10-10.json), [browser](ux-ui/acceptance/browser-speed-response-body-2026-10-10.json). Relay сначала получил actual RouterOS done testing, затем передал headers/первые16 bytes настоящего JSON и оборвал body. Теперь API502/понятный неизвестный результат вместо pending, история/прежний synthetic snapshot42/17/15/0 согласованы. Один capped10Mbit/s TCP3s test, native1/noauto retry, PC/3202/2/new message/reload/document fits/pageerror0. Свои disabled probe/history удалены, original IDs совпали, credentials/configuration RouterOS не менялись. Это controlled HTTP socket loss после headers, не independent WAN failure/cancelled native command.
|
||||
|
||||
**Runtime.** Backend ux-response100/version1.0.0-test.response100/image797979da82d6…; одна сборка изspeed98 +client/test/package-script files, source archive SHA в отчёте. Entry/node --check/pg_restore18.6/compose --wait passed, приватный .env backup; обновлён только BACKEND_IMAGE_TAG, frontend ux-ospf91/dependencies/migrations прежние. Label response100 — имя блока, не Git SHA. Backend/PG healthy,3 compose containers. Одна локальная фиксация без push; main UI99 всё ещё выполняется на неизменённом frontend source, его итог не заявлен. Квота37% использовано. Следующий101 — подтверждённые нарушения контраста/keyboard code после main99, затем context/финальная сводка.
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
# План реализации UX/UI по пятичасовым окнам
|
||||
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98. На стенде backend ux-speed98/frontend ux-ospf91; неизвестный native результат при transport loss теперь явно объяснён одинаково в API/history/UI, live2/2. Собственные fixtures очищены, credentials не менялись. Следующий12.5.99 — общая backend/main/context регрессия; backend/main уже запущены и пока не объявлены прошедшими. Актуальная внешняя матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт.
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98 и100;99 general main UI regression в работе. Backend ux-response100/frontend ux-ospf91: partial RouterOS response теперь prompt ECONNRESET/unknown receipt,7/7 transport и общая backend регрессия24 groups/171 node cases passed, live2/2/cleanup. 30-route live обзор нашёл нарушения контраста/keyboard;101 исправить после main99, затем context. Актуальная матрица 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–98. На стенде backend ux-speed98/frontend ux-ospf91; неизвестный native результат при transport loss теперь явно объяснён одинаково в API/history/UI, live2/2. Собственные fixtures очищены, credentials не менялись. Следующий12.5.99 — общая backend/main/context регрессия; backend/main уже запущены и пока не объявлены прошедшими. Актуальная внешняя матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт.
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98 и100;99 general main UI regression в работе. Backend ux-response100/frontend ux-ospf91: partial RouterOS response теперь prompt ECONNRESET/unknown receipt,7/7 transport и общая backend регрессия24 groups/171 node cases passed, live2/2/cleanup. 30-route live обзор нашёл нарушения контраста/keyboard;101 исправить после main99, затем context. Актуальная матрица 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 и оставшиеся профильные сетевые ограничения открыты.
|
||||
|
||||
|
||||
+20
-10
@@ -1,6 +1,6 @@
|
||||
# UX/UI: журнал реализации
|
||||
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98. На стенде backend ux-speed98/frontend ux-ospf91; неизвестный native результат при transport loss теперь явно объяснён одинаково в API/history/UI, live2/2. Собственные fixtures очищены, credentials не менялись. Следующий12.5.99 — общая backend/main/context регрессия; backend/main уже запущены и пока не объявлены прошедшими. Актуальная внешняя матрица docs/ux-ui-remaining-acceptance.md; этап12.5 открыт.
|
||||
Актуальное продолжение 2026-10-10: завершены12.5.93–98 и100;99 general main UI regression в работе. Backend ux-response100/frontend ux-ospf91: partial RouterOS response теперь prompt ECONNRESET/unknown receipt,7/7 transport и общая backend регрессия24 groups/171 node cases passed, live2/2/cleanup. 30-route live обзор нашёл нарушения контраста/keyboard;101 исправить после main99, затем context. Актуальная матрица 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,25 @@
|
||||
| 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–98 и ограничения ниже. Runtime backend ux-diagnostics89/frontend ux-ospf91. |
|
||||
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–98 и100;99 в работе и ограничения ниже. Runtime backend ux-diagnostics89/frontend ux-ospf91. |
|
||||
|
||||
## 12.5.100 — RouterOS: обрыв тела HTTP ответа больше не зависает (2026-10-10)
|
||||
|
||||
У ClientRequest и IncomingMessage разные error events. После получения headers частичный ответ не вызывал request error/end; запрос оставался pending даже после500ms timeout. Изолированная проверка воспроизвела6 failures по deadline1200ms для GET/POST/PUT/PATCH/DELETE/raw file reading; полныйsuccess/401 проходил. Добавлен общий watchRosResponseFailure на aborted/error во всех6 paths, очистка timer и существующий settle/AbortSignal cleanup дляPOST. Partial response отклоняется как ECONNRESET, без выдуманного ACK и повторных writes. Две прежние read-only file compatibility стратегии сохранены.
|
||||
|
||||
[Протокол](ux-ui/acceptance/routeros-response-transport-2026-10-10.json): после изменения7/7 включая complete success/401, probes.cancel/actual HTTP AbortSignal и byte file parser passed. Тест включён в test:ros-file. Локальный production build, новый test ESLint и Docker build прошли. Исходные2 prefer-const errors mikrotik.ts сохраняются, новые ошибки не добавлены; whole-file lint clean не заявлен. Общая backend регрессия повторена именно из-за изменения общей основы:24 npm groups/171 node:test cases/exit0. Console assertion scripts дополнительно входят в npm suite,171 не заявляется числом всех их assertions.
|
||||
|
||||
**Live.** [Native/API/PG](ux-ui/acceptance/speed-response-body-2026-10-10.json), [browser](ux-ui/acceptance/browser-speed-response-body-2026-10-10.json). Relay сначала получил actual RouterOS done testing, затем передал headers/первые16 bytes настоящего JSON и оборвал body. Теперь API502/понятный неизвестный результат вместо pending, история/прежний synthetic snapshot42/17/15/0 согласованы. Один capped10Mbit/s TCP3s test, native1/noauto retry, PC/3202/2/new message/reload/document fits/pageerror0. Свои disabled probe/history удалены, original IDs совпали, credentials/configuration RouterOS не менялись. Это controlled HTTP socket loss после headers, не independent WAN failure/cancelled native command.
|
||||
|
||||
**Runtime.** Backend ux-response100/version1.0.0-test.response100/image797979da82d6…; одна сборка изspeed98 +client/test/package-script files, source archive SHA в отчёте. Entry/node --check/pg_restore18.6/compose --wait passed, приватный .env backup; обновлён только BACKEND_IMAGE_TAG, frontend ux-ospf91/dependencies/migrations прежние. Label response100 — имя блока, не Git SHA. Backend/PG healthy,3 compose containers. Одна локальная фиксация без push; main UI99 всё ещё выполняется на неизменённом frontend source, его итог не заявлен. Квота37% использовано. Следующий101 — подтверждённые нарушения контраста/keyboard code после main99, затем context/финальная сводка.
|
||||
|
||||
## 12.5.99 — общая регрессия и live обзор (2026-10-10)
|
||||
|
||||
**В работе.** Backend98 npm test24 groups/164 node:test cases/exit0 прошёл с недоступным fixture DB URL; это не real-PG приёмка. Main UI regression запущена на3100 с BACKEND_INTERNAL_URL=http://127.0.0.1:1, API responses контролируются test fixtures. JSON reporter выдаёт итог после завершения; main/context пока не объявлены прошедшими. UI production source не меняется во время main run.493 исходных evidence files защищены snapshot, включая чужие изменённые GRE/VXLAN screenshots; восстановление — после main/context.
|
||||
|
||||
[Live обзор](ux-ui/acceptance/live-shell-a11y-2026-10-10.json):30 routes×1280/320=60, HTTP200/route errors0/pageerror0/document overflow0. Два автоматических read-only OSPF preview POST, apply/mutations0. Default dark theme/scoped axe выявил10 нарушений: alerts empty text, certificate badge/pre keyboard, containers hint, uptime hint; filters320 contrast не воспроизвёлся в устойчивом900ms повторе. Дополнительная светлая тема выявила sidebar subtitles и HR badge. Полная WCAG/все интеграции этим обзором не приняты; исправление101 после завершения main run.
|
||||
|
||||
Согласованность журналов: у всех numbered records есть даты, найден и удалён один точный дубликат12.5.21 изprogress/stage12/external; первая запись и дата2026-10-08 сохранены. Другие исторические данные не удалялись. В процессе внешнего HTTP контроля выявлен общий partial-response hang; исправление и отдельная фиксация100 ниже. Следующий шаг99 — дождаться main result, затем context; не перезапускать уже успешные unchanged suites.
|
||||
|
||||
## 12.5.98 — понятный неизвестный результат теста скорости (2026-10-10)
|
||||
|
||||
@@ -1130,14 +1148,6 @@ PG-8 browser unknown/reconciliation принят в этих границах. P
|
||||
|
||||
Основной backend4c12c55/frontend673e5ba не изменён. Новые backend/frontend исправления ещё не развёрнуты. Полный 12.5 открыт. Следующий 12.5.22 — сборка обновлённых образов и приёмка на стенде перед deployment. Локальный коммит без push.
|
||||
|
||||
## 12.5.21 — неопределённый исход speed-запуска и сверка с историей (2026-10-08)
|
||||
|
||||
В локальной строке запуска введён status unknown: «Сохранение не подтверждено», с видимым runId; это не новый статус серверного DTO (история API по-прежнему принимает только done/error). При обновлении истории незавершённая или неподтверждённая локальная строка сохраняется, если её идентификатора нет в ответе. Подтверждённая строка с тем же runId заменяет локальную, предупреждение снимается. Unknown не подменяет последний подтверждённый snapshot карточки пробы; предупреждение показано без destructive-оформления. Автоматического повторного сетевого теста нет. Ручной новый запуск остаётся доступен; предупреждение просит проверить историю перед повтором. Состояние локальной строки не сохраняется после перезагрузки страницы.
|
||||
|
||||
Проверки: 13/13 Playwright (uptime-speed-data и uptime-speed-unknown) за 27.7s, включая unknown → пустая история → done/error, сохранение TX42, один POST и адаптацию 320px. Это live-ветка UI с HTTP-моками, не real PG/browser proof. Scoped frontend typecheck (tmp/tsconfig-speed-check.json, исключён старый ignored tmp build context) и ESLint изменённых файлов прошли. Существующие null/zero, malformed DTO, свежесть, независимые источники и Ping-состояния сохранены.
|
||||
|
||||
Основной backend4c12c55/frontend673e5ba не изменён. Новые backend/frontend исправления ещё не развёрнуты. Полный 12.5 открыт. Следующий 12.5.22 — сборка обновлённых образов и приёмка на стенде перед deployment. Локальный коммит без push.
|
||||
|
||||
## 12.5.20 — сохранение подтверждённого speed snapshot при unknown receipt (2026-10-08)
|
||||
|
||||
Приостатке5%окнавыполненнебольшойлокальныйблокпередdeployment. Frontendcatch раньше ставилlastStatuserror/новыйlastRunAt любойошибкеPOSTspeed-test,включаяunknowncommit. Теперьподтверждённыйsnapshot пробысохраняется,еслиApiClientError502 содержитoutcomeunknown иrunId текущегозапроса. ЧужойrunId/неправильныйpayload/403/обычнаяошибка нераспознаютсякакэтотисход. Существующееservererrorсообщениепоказывается;новыекомпоненты/композицияReUIне менялись. Временнаястрокасамогозапросапо-прежнемуимеетstatuserror; полныйunknown-state/browserUX ещёнужнопроверить.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Оставшаяся внешняя приёмка — 2026-10-10
|
||||
|
||||
Это актуальная матрица после 12.5.98. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии.
|
||||
Это актуальная матрица после 12.5.100 (99 main/context в работе). Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии.
|
||||
|
||||
Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-speed98`, frontend `ux-ospf91`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты последнего сценария удалены, исходные11 коллекций×2 восстановлены; пароли не менялись.
|
||||
Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-response100`, frontend `ux-ospf91`; 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 — общая регрессия.
|
||||
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 в работе;100 partial-response hang исправлен/развёрнут. 101 — реальные a11y нарушения после main.
|
||||
3. **Заключительный профильный контроль:** после последнего исправления собрать только затронутую часть, проверить её live и обновить матрицу. Общую регрессию выполнить один раз на согласованном runtime.
|
||||
4. **Внешние зависимости:** Telegram/Portal/client OS/multi-WAN/scale проходят отдельную приёмку при наличии нужных аккаунтов, устройств и разрешений. Лабораторный результат двух CHR не закрывает их автоматически.
|
||||
|
||||
|
||||
+18
-8
@@ -1163,14 +1163,6 @@ SchedulerSnapshotError раньшеигнорировалruns[].okfalse уuptime
|
||||
|
||||
Основной backend4c12c55/frontend673e5ba не изменён. Новые backend/frontend исправления ещё не развёрнуты. Полный 12.5 открыт. Следующий 12.5.22 — сборка обновлённых образов и приёмка на стенде перед deployment. Локальный коммит без push.
|
||||
|
||||
## 12.5.21 — неопределённый исход speed-запуска и сверка с историей (2026-10-08)
|
||||
|
||||
В локальной строке запуска введён status unknown: «Сохранение не подтверждено», с видимым runId; это не новый статус серверного DTO (история API по-прежнему принимает только done/error). При обновлении истории незавершённая или неподтверждённая локальная строка сохраняется, если её идентификатора нет в ответе. Подтверждённая строка с тем же runId заменяет локальную, предупреждение снимается. Unknown не подменяет последний подтверждённый snapshot карточки пробы; предупреждение показано без destructive-оформления. Автоматического повторного сетевого теста нет. Ручной новый запуск остаётся доступен; предупреждение просит проверить историю перед повтором. Состояние локальной строки не сохраняется после перезагрузки страницы.
|
||||
|
||||
Проверки: 13/13 Playwright (uptime-speed-data и uptime-speed-unknown) за 27.7s, включая unknown → пустая история → done/error, сохранение TX42, один POST и адаптацию 320px. Это live-ветка UI с HTTP-моками, не real PG/browser proof. Scoped frontend typecheck (tmp/tsconfig-speed-check.json, исключён старый ignored tmp build context) и ESLint изменённых файлов прошли. Существующие null/zero, malformed DTO, свежесть, независимые источники и Ping-состояния сохранены.
|
||||
|
||||
Основной backend4c12c55/frontend673e5ba не изменён. Новые backend/frontend исправления ещё не развёрнуты. Полный 12.5 открыт. Следующий 12.5.22 — сборка обновлённых образов и приёмка на стенде перед deployment. Локальный коммит без push.
|
||||
|
||||
## 12.5.22 — новые Docker-образы и real browser speed unknown (2026-10-08)
|
||||
|
||||
Из зафиксированного source8782054078304f36cc611876af2d17f87b857f60 подготовлены отдельные frontend/backend contexts и последовательно собраны production-образы на Debian-стенде. Frontend production build и проверка TypeScript внутри Docker прошли; backend contracts/TypeScript build прошёл. Незакоммиченные изменения, .env, ключи и локальные node_modules в сборку не передавались. Образы не публиковались.
|
||||
@@ -2244,3 +2236,21 @@ API502, history error/TXRX/Pingnull, probe error с прежними42/17/15/0;
|
||||
[Native/API/PG](ux-ui/acceptance/speed-message-2026-10-10.json) и [browser](ux-ui/acceptance/browser-speed-message-2026-10-10.json): повторён только изменённый receipt path, одна capped10Mbit/s TCP3s команда, реальное закрытие socket после передачи, native independently done, API/history содержат новое сообщение; прежние синтетические42/17/15/0 сохранены, native1/noauto retry. Live1280/3202/2, сообщение видно в probe card, reload/document fits/pageerror0/UI command POST0. Свои disabled probe/history удалены, исходные IDs совпали, только3 compose containers/backend/PG healthy; RouterOS/credentials не менялись.
|
||||
|
||||
При согласовании указателей94–97 обнаружено, что массовая замена также затронула исторический абзац77 в плане/протоколе. Восстановлен точный абзац из40f730b, история/дата2026-10-09 сохранены; следующие обновления ограничены текущими указателями. Следующий99 — одна общая backend/main/context регрессия на текущем source, с восстановлением исходных доказательств, затем итоговая сводка. General backend/main runs уже запущены, их результат этим блоком не заявлен. Квота23% использовано; этап12.5 открыт. Один локальный commit без push.
|
||||
|
||||
## 12.5.99 — общая регрессия и live обзор (2026-10-10)
|
||||
|
||||
**В работе.** Backend98 npm test24 groups/164 node:test cases/exit0 прошёл с недоступным fixture DB URL; это не real-PG приёмка. Main UI regression запущена на3100 с BACKEND_INTERNAL_URL=http://127.0.0.1:1, API responses контролируются test fixtures. JSON reporter выдаёт итог после завершения; main/context пока не объявлены прошедшими. UI production source не меняется во время main run.493 исходных evidence files защищены snapshot, включая чужие изменённые GRE/VXLAN screenshots; восстановление — после main/context.
|
||||
|
||||
[Live обзор](ux-ui/acceptance/live-shell-a11y-2026-10-10.json):30 routes×1280/320=60, HTTP200/route errors0/pageerror0/document overflow0. Два автоматических read-only OSPF preview POST, apply/mutations0. Default dark theme/scoped axe выявил10 нарушений: alerts empty text, certificate badge/pre keyboard, containers hint, uptime hint; filters320 contrast не воспроизвёлся в устойчивом900ms повторе. Дополнительная светлая тема выявила sidebar subtitles и HR badge. Полная WCAG/все интеграции этим обзором не приняты; исправление101 после завершения main run.
|
||||
|
||||
Согласованность журналов: у всех numbered records есть даты, найден и удалён один точный дубликат12.5.21 изprogress/stage12/external; первая запись и дата2026-10-08 сохранены. Другие исторические данные не удалялись. В процессе внешнего HTTP контроля выявлен общий partial-response hang; исправление и отдельная фиксация100 ниже. Следующий шаг99 — дождаться main result, затем context; не перезапускать уже успешные unchanged suites.
|
||||
|
||||
## 12.5.100 — RouterOS: обрыв тела HTTP ответа больше не зависает (2026-10-10)
|
||||
|
||||
У ClientRequest и IncomingMessage разные error events. После получения headers частичный ответ не вызывал request error/end; запрос оставался pending даже после500ms timeout. Изолированная проверка воспроизвела6 failures по deadline1200ms для GET/POST/PUT/PATCH/DELETE/raw file reading; полныйsuccess/401 проходил. Добавлен общий watchRosResponseFailure на aborted/error во всех6 paths, очистка timer и существующий settle/AbortSignal cleanup дляPOST. Partial response отклоняется как ECONNRESET, без выдуманного ACK и повторных writes. Две прежние read-only file compatibility стратегии сохранены.
|
||||
|
||||
[Протокол](ux-ui/acceptance/routeros-response-transport-2026-10-10.json): после изменения7/7 включая complete success/401, probes.cancel/actual HTTP AbortSignal и byte file parser passed. Тест включён в test:ros-file. Локальный production build, новый test ESLint и Docker build прошли. Исходные2 prefer-const errors mikrotik.ts сохраняются, новые ошибки не добавлены; whole-file lint clean не заявлен. Общая backend регрессия повторена именно из-за изменения общей основы:24 npm groups/171 node:test cases/exit0. Console assertion scripts дополнительно входят в npm suite,171 не заявляется числом всех их assertions.
|
||||
|
||||
**Live.** [Native/API/PG](ux-ui/acceptance/speed-response-body-2026-10-10.json), [browser](ux-ui/acceptance/browser-speed-response-body-2026-10-10.json). Relay сначала получил actual RouterOS done testing, затем передал headers/первые16 bytes настоящего JSON и оборвал body. Теперь API502/понятный неизвестный результат вместо pending, история/прежний synthetic snapshot42/17/15/0 согласованы. Один capped10Mbit/s TCP3s test, native1/noauto retry, PC/3202/2/new message/reload/document fits/pageerror0. Свои disabled probe/history удалены, original IDs совпали, credentials/configuration RouterOS не менялись. Это controlled HTTP socket loss после headers, не independent WAN failure/cancelled native command.
|
||||
|
||||
**Runtime.** Backend ux-response100/version1.0.0-test.response100/image797979da82d6…; одна сборка изspeed98 +client/test/package-script files, source archive SHA в отчёте. Entry/node --check/pg_restore18.6/compose --wait passed, приватный .env backup; обновлён только BACKEND_IMAGE_TAG, frontend ux-ospf91/dependencies/migrations прежние. Label response100 — имя блока, не Git SHA. Backend/PG healthy,3 compose containers. Одна локальная фиксация без push; main UI99 всё ещё выполняется на неизменённом frontend source, его итог не заявлен. Квота37% использовано. Следующий101 — подтверждённые нарушения контраста/keyboard code после main99, затем context/финальная сводка.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Тестовый сервер UX/UI — 2026-10-10
|
||||
|
||||
Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-speed98/version1.0.0-test.speed98, frontend ux-ospf91/version1.0.0-test.ospf91; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние.
|
||||
Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-response100/version1.0.0-test.response100, frontend ux-ospf91/version1.0.0-test.ospf91; 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-speed98 и mmapp-test/frontend:ux-ospf91; запущены |
|
||||
| Образы приложения | mmapp-test/backend:ux-response100 и mmapp-test/frontend:ux-ospf91; запущены |
|
||||
|
||||
Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example).
|
||||
|
||||
@@ -757,3 +757,13 @@ API502, history error/TXRX/Pingnull, probe error с прежними42/17/15/0;
|
||||
[Native/API/PG](ux-ui/acceptance/speed-message-2026-10-10.json) и [browser](ux-ui/acceptance/browser-speed-message-2026-10-10.json): повторён только изменённый receipt path, одна capped10Mbit/s TCP3s команда, реальное закрытие socket после передачи, native independently done, API/history содержат новое сообщение; прежние синтетические42/17/15/0 сохранены, native1/noauto retry. Live1280/3202/2, сообщение видно в probe card, reload/document fits/pageerror0/UI command POST0. Свои disabled probe/history удалены, исходные IDs совпали, только3 compose containers/backend/PG healthy; RouterOS/credentials не менялись.
|
||||
|
||||
При согласовании указателей94–97 обнаружено, что массовая замена также затронула исторический абзац77 в плане/протоколе. Восстановлен точный абзац из40f730b, история/дата2026-10-09 сохранены; следующие обновления ограничены текущими указателями. Следующий99 — одна общая backend/main/context регрессия на текущем source, с восстановлением исходных доказательств, затем итоговая сводка. General backend/main runs уже запущены, их результат этим блоком не заявлен. Квота23% использовано; этап12.5 открыт. Один локальный commit без push.
|
||||
|
||||
## 12.5.100 — RouterOS: обрыв тела HTTP ответа больше не зависает (2026-10-10)
|
||||
|
||||
У ClientRequest и IncomingMessage разные error events. После получения headers частичный ответ не вызывал request error/end; запрос оставался pending даже после500ms timeout. Изолированная проверка воспроизвела6 failures по deadline1200ms для GET/POST/PUT/PATCH/DELETE/raw file reading; полныйsuccess/401 проходил. Добавлен общий watchRosResponseFailure на aborted/error во всех6 paths, очистка timer и существующий settle/AbortSignal cleanup дляPOST. Partial response отклоняется как ECONNRESET, без выдуманного ACK и повторных writes. Две прежние read-only file compatibility стратегии сохранены.
|
||||
|
||||
[Протокол](ux-ui/acceptance/routeros-response-transport-2026-10-10.json): после изменения7/7 включая complete success/401, probes.cancel/actual HTTP AbortSignal и byte file parser passed. Тест включён в test:ros-file. Локальный production build, новый test ESLint и Docker build прошли. Исходные2 prefer-const errors mikrotik.ts сохраняются, новые ошибки не добавлены; whole-file lint clean не заявлен. Общая backend регрессия повторена именно из-за изменения общей основы:24 npm groups/171 node:test cases/exit0. Console assertion scripts дополнительно входят в npm suite,171 не заявляется числом всех их assertions.
|
||||
|
||||
**Live.** [Native/API/PG](ux-ui/acceptance/speed-response-body-2026-10-10.json), [browser](ux-ui/acceptance/browser-speed-response-body-2026-10-10.json). Relay сначала получил actual RouterOS done testing, затем передал headers/первые16 bytes настоящего JSON и оборвал body. Теперь API502/понятный неизвестный результат вместо pending, история/прежний synthetic snapshot42/17/15/0 согласованы. Один capped10Mbit/s TCP3s test, native1/noauto retry, PC/3202/2/new message/reload/document fits/pageerror0. Свои disabled probe/history удалены, original IDs совпали, credentials/configuration RouterOS не менялись. Это controlled HTTP socket loss после headers, не independent WAN failure/cancelled native command.
|
||||
|
||||
**Runtime.** Backend ux-response100/version1.0.0-test.response100/image797979da82d6…; одна сборка изspeed98 +client/test/package-script files, source archive SHA в отчёте. Entry/node --check/pg_restore18.6/compose --wait passed, приватный .env backup; обновлён только BACKEND_IMAGE_TAG, frontend ux-ospf91/dependencies/migrations прежние. Label response100 — имя блока, не Git SHA. Backend/PG healthy,3 compose containers. Одна локальная фиксация без push; main UI99 всё ещё выполняется на неизменённом frontend source, его итог не заявлен. Квота37% использовано. Следующий101 — подтверждённые нарушения контраста/keyboard code после main99, затем context/финальная сводка.
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"date": "2026-10-10",
|
||||
"cases": [
|
||||
{
|
||||
"width": 1280,
|
||||
"errorHistoryVisible": true,
|
||||
"previousSnapshot42and17Preserved": true,
|
||||
"reload": true,
|
||||
"documentFits": true
|
||||
},
|
||||
{
|
||||
"width": 320,
|
||||
"errorHistoryVisible": true,
|
||||
"previousSnapshot42and17Preserved": true,
|
||||
"reload": true,
|
||||
"documentFits": true
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"httpMocks": false,
|
||||
"uiNativePosts": 0
|
||||
}
|
||||
@@ -0,0 +1,703 @@
|
||||
{
|
||||
"date": "2026-10-10",
|
||||
"runtime": {
|
||||
"backend": "ux-speed98",
|
||||
"frontend": "ux-ospf91"
|
||||
},
|
||||
"httpMocks": false,
|
||||
"readOnly": true,
|
||||
"cases": [
|
||||
{
|
||||
"route": "alerts",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".py-12 > p"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "alerts",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".py-12 > .text-sm"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "asns",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "asns",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "backups",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "backups",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "bgp",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "bgp",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "certificates",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".text-success-foreground"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "scrollable-region-focusable",
|
||||
"impact": "serious",
|
||||
"description": "Ensure elements that have scrollable content are accessible by keyboard in Safari",
|
||||
"targets": [
|
||||
[
|
||||
"div:nth-child(1) > pre"
|
||||
],
|
||||
[
|
||||
"div:nth-child(3) > pre"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "certificates",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".text-success-foreground"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "scrollable-region-focusable",
|
||||
"impact": "serious",
|
||||
"description": "Ensure elements that have scrollable content are accessible by keyboard in Safari",
|
||||
"targets": [
|
||||
[
|
||||
"div:nth-child(3) > pre"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "communities",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "communities",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "containers",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".bg-info\\/5 > div > .text-info"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "containers",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".bg-info\\/5 > div > .text-info"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "dashboard",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "dashboard",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "data-collection",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "data-collection",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "domains",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "domains",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "filters",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "filters",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".bg-primary"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "firewall",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "firewall",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "gre",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "gre",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "ip-ranges",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "ip-ranges",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "ipsec",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "ipsec",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "network-map",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "network-map",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "ospf",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "ospf",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "probes",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "probes",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "recursive-routes",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "recursive-routes",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "releases",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "releases",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "route-optimizer",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "route-optimizer",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "servers",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "servers",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "settings",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "settings",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "statistics",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "statistics",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "terminal",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "terminal",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "traffic",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": [
|
||||
{
|
||||
"path": "/api/traffic/servers/srv1/interfaces",
|
||||
"status": 400
|
||||
},
|
||||
{
|
||||
"path": "/api/traffic/servers/srv1",
|
||||
"status": 400
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"route": "traffic",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": [
|
||||
{
|
||||
"path": "/api/traffic/servers/srv1/interfaces",
|
||||
"status": 400
|
||||
},
|
||||
{
|
||||
"path": "/api/traffic/servers/srv1",
|
||||
"status": 400
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"route": "uptime",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
|
||||
"targets": [
|
||||
[
|
||||
".text-muted-foreground\\/80"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "uptime",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "users",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "users",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "vxlan",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "vxlan",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "wireguard",
|
||||
"width": 1280,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
},
|
||||
{
|
||||
"route": "wireguard",
|
||||
"width": 320,
|
||||
"httpStatus": 200,
|
||||
"fits": true,
|
||||
"title": "MikrotikManager",
|
||||
"violations": [],
|
||||
"apiFailures": []
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"writes": [
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/servers/1/ospf/optimize/preview"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/servers/1/ospf/optimize/preview"
|
||||
}
|
||||
],
|
||||
"automaticReadOnlyRequests": [
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/servers/1/ospf/optimize/preview"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/servers/1/ospf/optimize/preview"
|
||||
}
|
||||
],
|
||||
"mutations": [],
|
||||
"note": "Two automatic OSPF optimizer preview POSTs only; no apply/mutation requests. Scoped axe at700ms after fonts ready; not full WCAG or functional acceptance of all integrations."
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"date": "2026-10-10",
|
||||
"runtime": {
|
||||
"backend": "ux-response100",
|
||||
"version": "1.0.0-test.response100",
|
||||
"imageId": "sha256:797979da82d6bd10147bd57557c65cc28a61b1e583abed13ed7326635d4e5adf",
|
||||
"frontend": "ux-ospf91"
|
||||
},
|
||||
"source": {
|
||||
"base": "build-speed98",
|
||||
"archiveSha256": "08e9b4bb3a70c5d9d20e0ffef387d9bbba7bcc51f80968be740c7c64982dc5da",
|
||||
"workingTreeOverrides": [
|
||||
"backend/src/services/mikrotik.ts",
|
||||
"backend/src/services/mikrotik-response.test.ts",
|
||||
"backend/package.json"
|
||||
],
|
||||
"revisionLabel": "response100 (stage label, not Git SHA)"
|
||||
},
|
||||
"before": {
|
||||
"boundedTests": 7,
|
||||
"passed": 1,
|
||||
"failed": 6,
|
||||
"reason": "Incomplete IncomingMessage left promise pending past500ms timeout; test1200ms deadline rejected"
|
||||
},
|
||||
"after": {
|
||||
"boundedTests": 7,
|
||||
"passed": 7,
|
||||
"failed": 0,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"raw file POST"
|
||||
],
|
||||
"completeSuccessAnd401": true,
|
||||
"mutationRetries": 0,
|
||||
"fileCompatibilityReadStrategies": 2
|
||||
},
|
||||
"checks": {
|
||||
"abortSignalAndProbeCancellation": true,
|
||||
"fileByteParser": true,
|
||||
"localProductionBuild": true,
|
||||
"dockerProductionBuild": true,
|
||||
"entryNodeCheck": true,
|
||||
"pgRestore": "18.6",
|
||||
"composeHealthy": true,
|
||||
"backendNpmTest": {
|
||||
"groups": 24,
|
||||
"nodeTestCases": 171,
|
||||
"reportedFailures": 0,
|
||||
"exitCode": 0,
|
||||
"database": "Deliberately unavailable fixture URL; no external DB writes"
|
||||
},
|
||||
"lintNewTest": true,
|
||||
"existingMikrotikPreferConstErrors": 2
|
||||
},
|
||||
"live": {
|
||||
"nativeReport": "speed-response-body-2026-10-10.json",
|
||||
"browserReport": "browser-speed-response-body-2026-10-10.json",
|
||||
"nativeCommands": 1,
|
||||
"durationSec": 3,
|
||||
"rateLimitBps": 10000000,
|
||||
"body": "First16 bytes of actual completed native JSON delivered; relay closed socket before remaining body",
|
||||
"api502": true,
|
||||
"unknownMessage": true,
|
||||
"priorSnapshotPreserved": true,
|
||||
"automaticRetry": false,
|
||||
"uiCases": 2,
|
||||
"cleanup": true
|
||||
},
|
||||
"limits": [
|
||||
"HTTP localhost partial-response tests plus real RouterOS command through controlled relay; not independent physical WAN loss",
|
||||
"Complete malformed PATCH JSON semantics, general response size limits and durable cancellation not changed",
|
||||
"Main/context UI matrix still pending; frontend unchanged"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"date": "2026-10-10",
|
||||
"name": "mm-body100-1791572367426",
|
||||
"rateLimitBps": 10000000,
|
||||
"durationSec": 3,
|
||||
"syntheticPreviousSnapshot": {
|
||||
"txAvgMbps": 42,
|
||||
"rxAvgMbps": 17,
|
||||
"pingRttMs": 15,
|
||||
"pingLossPct": 0
|
||||
},
|
||||
"httpMocks": false,
|
||||
"routerOsMocks": false,
|
||||
"nativeCompletion": {
|
||||
"status": "done testing",
|
||||
"responseRows": 5,
|
||||
"httpStatus": 200
|
||||
},
|
||||
"receiptPhase": "partial-response-body",
|
||||
"receiptSocketDestroyed": true,
|
||||
"httpStatus": 502,
|
||||
"receipt": {
|
||||
"error": "Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском."
|
||||
},
|
||||
"nativeCount": 1,
|
||||
"probe": {
|
||||
"id": "mm-body100-1791572367426",
|
||||
"last_status": "error",
|
||||
"last_tx_avg_mbps": 42,
|
||||
"last_rx_avg_mbps": 17,
|
||||
"last_ping_rtt_ms": 15,
|
||||
"last_ping_loss_pct": 0,
|
||||
"last_error": "Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском."
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"id": "mm-body100-1791572367426",
|
||||
"status": "error",
|
||||
"tx_avg_mbps": null,
|
||||
"rx_avg_mbps": null,
|
||||
"ping_rtt_ms": null,
|
||||
"ping_loss_pct": null,
|
||||
"error": "Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском."
|
||||
}
|
||||
],
|
||||
"automaticRetry": false,
|
||||
"limits": [
|
||||
"Real Node HTTP client socket closed after request forwarded; RouterOS independently completed. Not physical WAN loss or cancelled native command.",
|
||||
"Previous metrics deliberately seeded on own disabled probe, not new real measurements.",
|
||||
"History error means application did not obtain confirmed test result; native completion was observed only by independent relay."
|
||||
],
|
||||
"cleanupHistory": true,
|
||||
"cleanupProbes": true
|
||||
}
|
||||
Reference in new issue
Block a user