diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index c6f6103b..f27668ca 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -141,3 +141,7 @@ BGP-prefix evaluator, отдельное live GRE расписание и recove ## Реальный отказ bandwidth-аутентификации — 2026-10-08 12.5.25 [native/API/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): authentication failed→HTTP502/русская UI-ошибка, history error/TXRXnull; probe previousTX42 сохранён. Native1/POST[502]/refresh/reload/320fits/JS0, без HTTP/RouterOS-моков. Тестовое имя изменялось только в выделенной app DB и восстановлено; RouterOS accounts не менялись. Temporarycontainers/network/3018 закрыты, testprobe удалена; основнаяhistory5/runtime8782054 сохранены. Подготовительный слишком длинныйuser отклонён по длине; accepted run отдельно. ROS-2 authentication failure принят; остальные native failures ещё открыты. Следующий12.5.26 — unreachable destination. + +## Исправление Next proxy timeout — 2026-10-08 + +12.5.26 [real frontend500/backend error-history](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json) выявил30s proxy timeout. Локально proxyTimeout180s; реальная Next proxy regression31s/TypeScript/ESLint passed. Backend сохраняет предыдущий TX42; native can not connect не подтверждён. Runtime8782054 прежний; destination восстановлен/testprobe удалена/temporarycontainers-network-3018 закрыты. Следующий12.5.27 — build/real browser retry/deployment исправленного frontend. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 14d79faa..b6395e55 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-08: 12.5.25 завершён — реальный CHR authentication failed → HTTP502/понятная UI-ошибка/history error с null скоростями; предыдущий TX42 сохранён, native1/без автоповтора, refresh/reload/320px/JS0. Runtime8782054 сохранён. Следующий12.5.26 — ROS-2: недоступное назначение bandwidth-test и согласованность HTTP/UI/history. Полный12.5 открыт. +Актуальное продолжение 2026-10-08: 12.5.26 обнаружил proxy-дефект: при недоступном назначении Next обрывал запрос через30s/HTTP500, backend сохранил error/history и прежний TX42. Локально proxyTimeout180s исправлен, regression31s/typecheck/ESLint прошли. Runtime8782054 прежний. Следующий12.5.27 — frontend build, повторная real browser timeout-проверка и deployment. Native can not connect ещё не подтверждён. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-08. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-08 -Этапы0–11 завершены в описанных локальных границах. Этап12 остаётся открытым. На161.104.46.222 развёрнуты backend/frontend8782054; два CHR подключены. PG backup/restore/rollback, single-instance quiescence, JWT/RBAC и browser restore приняты в границах журнала. PG-8 проверен с настоящими PG/native и введённой после COMMIT ошибкой подтверждения; новый browser UI сохраняет snapshot и сверяет историю. ROS-8/9 API/SQL/native приняты в описанных границах. Browser-смена пары/длительности и удаление во время native-теста приняты в12.5.24. Реальный отказ bandwidth-аутентификации принят в12.5.25. Следующий12.5.26 — ROS-2: недоступное назначение и согласованность HTTP/UI/history. [Протокол](ux-ui-external-acceptance.md) и [журнал](ux-ui-stage-12.md) сохраняют точные доказательства и ограничения. +Этапы0–11 завершены в описанных локальных границах. Этап12 остаётся открытым. На161.104.46.222 развёрнуты backend/frontend8782054; два CHR подключены. PG backup/restore/rollback, single-instance quiescence, JWT/RBAC и browser restore приняты в границах журнала. PG-8 проверен с настоящими PG/native и введённой после COMMIT ошибкой подтверждения; новый browser UI сохраняет snapshot и сверяет историю. ROS-8/9 API/SQL/native приняты в описанных границах. Browser-смена пары/длительности и удаление во время native-теста приняты в12.5.24. Реальный отказ bandwidth-аутентификации принят в12.5.25. 12.5.26 обнаружил и локально исправил30s timeout Next proxy. Следующий12.5.27 — новый frontend build/real browser timeout/deployment. [Протокол](ux-ui-external-acceptance.md) и [журнал](ux-ui-stage-12.md) сохраняют точные доказательства и ограничения. Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 5e9f08da..ab1260ec 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-08: 12.5.25 завершён — реальный CHR authentication failed → HTTP502/понятная UI-ошибка/history error с null скоростями; предыдущий TX42 сохранён, native1/без автоповтора, refresh/reload/320px/JS0. Runtime8782054 сохранён. Следующий12.5.26 — ROS-2: недоступное назначение bandwidth-test и согласованность HTTP/UI/history. Полный12.5 открыт. +Актуальное продолжение 2026-10-08: 12.5.26 обнаружил proxy-дефект: при недоступном назначении Next обрывал запрос через30s/HTTP500, backend сохранил error/history и прежний TX42. Локально proxyTimeout180s исправлен, regression31s/typecheck/ESLint прошли. Runtime8782054 прежний. Следующий12.5.27 — frontend build, повторная real browser timeout-проверка и deployment. Native can not connect ещё не подтверждён. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -34,6 +34,14 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в описанных границах:12.3.83,main1186/1186,context221/221. Этап остаётся в работе: стенд12.5.1–3 развёрнут,bootstrap/smoke проверены;остальные сценарии12.5 не выполнены. | +## 12.5.26 — тайм-аут недоступного назначения и исправление Next proxy (2026-10-08) + +[Real failure evidence](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json): source8782054, выделенная БД, назначение2 временно заменено в app DB на192.0.2.250. Реальный bandwidth POST от CHR1 не вернул native rows до30s. Backend записал history error/TXRXnull и сохранил предыдущий probeTX42; frontend rewrite оборвал запрос с socket hang up/ECONNRESET и вернулHTTP500 раньше структурированного ответа backend. Целевая UI-проверка отклонила500; она не объявлена passed. Это транспортный timeout, не подтверждённый native can not connect. + +В установленном Next16.2.4 найден default proxyTimeout30000. В next.config.ts задан experimental.proxyTimeout180000, дольше120s ожидания speed-команды в UI. Добавлен tests/integration/next-proxy-timeout.mjs: загрузка реальной конфигурации проекта, настоящие loopback sockets и установленный Next proxy; delayed backend502JSON после31s доходит до caller. Регрессия, scoped frontend TypeScript и ESLint прошли. Сценарий использует fixture backend response для проверки proxy, не выдаётся за RouterOS proof. Backend/общие UI-компоненты не менялись. + +Temporarycontainers/network/3018 закрыты; destinationhost восстановлен и проверен, testprobe удалена. Основной runtime8782054 прежний. Исправление требует нового frontend build: следующий12.5.27 — real browser timeout-проверка на новом образе и deployment после успеха. ROS-2 native can not connect/busy/disconnect/abort остаются открытыми. План и журнал обновлены, локальный коммит без push. + ## 12.5.25 — реальный отказ bandwidth-аутентификации (2026-10-08) [Real API/native/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): production8782054, выделенная БД mmapp_acceptance_20261007, изолированная Docker network/SSH3018. Только в app DB временно изменён username назначения2 на несуществующий тестовый; исходное значение сохранено в памяти и восстановлено при штатном завершении. Учётные записи и конфигурация RouterOS не менялись. Scheduler admission закрыт только внутри isolated backend. Guard подтвердил выделенную БД до команды; предыдущий TX42 был явно подготовлен как DB fixture. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index c1b0b5bf..519beee1 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-08: 12.5.25 завершён — реальный CHR authentication failed → HTTP502/понятная UI-ошибка/history error с null скоростями; предыдущий TX42 сохранён, native1/без автоповтора, refresh/reload/320px/JS0. Runtime8782054 сохранён. Следующий12.5.26 — ROS-2: недоступное назначение bandwidth-test и согласованность HTTP/UI/history. Полный12.5 открыт. +Актуальное продолжение 2026-10-08: 12.5.26 обнаружил proxy-дефект: при недоступном назначении Next обрывал запрос через30s/HTTP500, backend сохранил error/history и прежний TX42. Локально proxyTimeout180s исправлен, regression31s/typecheck/ESLint прошли. Runtime8782054 прежний. Следующий12.5.27 — frontend build, повторная real browser timeout-проверка и deployment. Native can not connect ещё не подтверждён. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -1218,3 +1218,11 @@ Temporaryfrontend/backend/network удалены,3018туннель закрыт После «Обновить» и reload история error сохранена; nativeCalls1/POST[502], автоповтора нет, JSerrors0/320px fits. HTTP/RouterOS-моков нет. Подготовительный запрос с чрезмерно длинным тестовым именем был отклонён RouterOSHTTP400 по длинеuser до целевого сценария; после исправления fixture выполнен отдельный принятый прогон. Это ручная валидация, не retry продукта. Temporaryfrontend/backend/network удалены,3018туннель закрыт, fixtureprobe удалена. В выделенной БД username назначения восстановлен и проверен без вывода секрета; основная история5 сохранена, runtime8782054 исправен. Продуктовый код не менялся, build/deployment не выполнялся. ROS-2 authentication failure принят; unreachable/busy/disconnect/abort и PortalSSO остаются открытыми. Следующий12.5.26 — недоступное назначение bandwidth-test и проверка HTTP/UI/history. План/паспорт/протокол обновлены; локальный коммит без push. + +## 12.5.26 — тайм-аут недоступного назначения и исправление Next proxy (2026-10-08) + +[Real failure evidence](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json): source8782054, выделенная БД, назначение2 временно заменено в app DB на192.0.2.250. Реальный bandwidth POST от CHR1 не вернул native rows до30s. Backend записал history error/TXRXnull и сохранил предыдущий probeTX42; frontend rewrite оборвал запрос с socket hang up/ECONNRESET и вернулHTTP500 раньше структурированного ответа backend. Целевая UI-проверка отклонила500; она не объявлена passed. Это транспортный timeout, не подтверждённый native can not connect. + +В установленном Next16.2.4 найден default proxyTimeout30000. В next.config.ts задан experimental.proxyTimeout180000, дольше120s ожидания speed-команды в UI. Добавлен tests/integration/next-proxy-timeout.mjs: загрузка реальной конфигурации проекта, настоящие loopback sockets и установленный Next proxy; delayed backend502JSON после31s доходит до caller. Регрессия, scoped frontend TypeScript и ESLint прошли. Сценарий использует fixture backend response для проверки proxy, не выдаётся за RouterOS proof. Backend/общие UI-компоненты не менялись. + +Temporarycontainers/network/3018 закрыты; destinationhost восстановлен и проверен, testprobe удалена. Основной runtime8782054 прежний. Исправление требует нового frontend build: следующий12.5.27 — real browser timeout-проверка на новом образе и deployment после успеха. ROS-2 native can not connect/busy/disconnect/abort остаются открытыми. План и журнал обновлены, локальный коммит без push. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index d6232df2..7959fc03 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -149,3 +149,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 root@161.104.46.222 ## Реальный отказ bandwidth-аутентификации — 2026-10-08 12.5.25 [native/API/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): authentication failed→HTTP502/русская UI-ошибка, history error/TXRXnull; probe previousTX42 сохранён. Native1/POST[502]/refresh/reload/320fits/JS0, без HTTP/RouterOS-моков. Тестовое имя изменялось только в выделенной app DB и восстановлено; RouterOS accounts не менялись. Temporarycontainers/network/3018 закрыты, testprobe удалена; основнаяhistory5/runtime8782054 сохранены. Подготовительный слишком длинныйuser отклонён по длине; accepted run отдельно. ROS-2 authentication failure принят; остальные native failures ещё открыты. Следующий12.5.26 — unreachable destination. + +## Исправление Next proxy timeout — 2026-10-08 + +12.5.26 [real frontend500/backend error-history](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json) выявил30s proxy timeout. Локально proxyTimeout180s; реальная Next proxy regression31s/TypeScript/ESLint passed. Backend сохраняет предыдущий TX42; native can not connect не подтверждён. Runtime8782054 прежний; destination восстановлен/testprobe удалена/temporarycontainers-network-3018 закрыты. Следующий12.5.27 — build/real browser retry/deployment исправленного frontend. diff --git a/docs/ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json b/docs/ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json new file mode 100644 index 00000000..064ee73b --- /dev/null +++ b/docs/ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json @@ -0,0 +1,40 @@ +{ + "date": "2026-10-08", + "source": "8782054", + "database": "mmapp_acceptance_20261007", + "frontendReceipt": 500, + "proxyLog": "Failed to proxy speed-test: socket hang up ECONNRESET", + "nativeCalls": 1, + "nativeStatuses": [], + "snapshot": { + "last_status": "error", + "last_tx_avg_mbps": 42, + "last_rx_avg_mbps": null, + "last_run_at": "2026-10-08T02:33:03.080Z" + }, + "history": { + "id": "speed-1791426754414", + "probeId": "acceptance-browser-unreachable", + "srcServerId": "1", + "dstServerId": "2", + "srcInterface": "", + "dstInterface": "", + "protocol": "tcp", + "direction": "transmit", + "durationSec": 3, + "txAvgMbps": null, + "rxAvgMbps": null, + "status": "error", + "error": "BTTest timeout/socket hang up: \u043f\u0440\u043e\u0432\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c destination, /tool bandwidth-server, firewall \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432", + "createdAt": "2026-10-08T02:33:03.083Z", + "srcAddress": null, + "dstAddress": null, + "srcInterfaceAddress": null, + "dstInterfaceAddress": null, + "afterBtPing": { + "rttMs": null, + "lossPct": null, + "error": null + } + } +} \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index 148edbb2..b0c1165c 100644 --- a/next.config.ts +++ b/next.config.ts @@ -5,6 +5,9 @@ const nextConfig: NextConfig = { output: "standalone", experimental: { proxyClientMaxBodySize: "512mb", + // Speed commands include RouterOS waits and post-test Ping; the UI allows 120s. + // Let the backend return its structured outcome before the rewrite times out. + proxyTimeout: 180_000, }, async rewrites() { const backendUrl = backendInternalUrl(); diff --git a/tests/integration/next-proxy-timeout.mjs b/tests/integration/next-proxy-timeout.mjs new file mode 100644 index 00000000..8a72efbd --- /dev/null +++ b/tests/integration/next-proxy-timeout.mjs @@ -0,0 +1,46 @@ +import assert from 'node:assert/strict'; +import http from 'node:http'; +import url from 'node:url'; +import configExports from 'next/dist/server/config.js'; +import constants from 'next/constants.js'; +import proxyExports from 'next/dist/server/lib/router-utils/proxy-request.js'; +const loadConfig = configExports.default; +const { PHASE_DEVELOPMENT_SERVER } = constants; +const { proxyRequest } = proxyExports; + +// Exercise the installed Next proxy with the project's loaded config and real sockets. +// A delayed structured failure must reach the caller beyond Next's default 30s. +(async () => { + const config = await loadConfig(PHASE_DEVELOPMENT_SERVER, process.cwd()); + const pending = new Set(); + const backend = http.createServer((request, response) => { + request.resume(); + const timer = setTimeout(() => { + pending.delete(timer); + response.writeHead(502, { 'content-type': 'application/json' }); + response.end(JSON.stringify({ error: 'Backend timeout receipt', outcome: 'unknown' })); + }, 31_000); + pending.add(timer); + }); + const proxy = http.createServer((request, response) => { + const target = url.parse(`http://127.0.0.1:${backend.address().port}${request.url}`, true); + proxyRequest(request, response, target, undefined, undefined, config.experimental.proxyTimeout) + .catch(() => { if (!response.headersSent) response.writeHead(500); response.end(); }); + }); + const listen = server => new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); + try { + await listen(backend); await listen(proxy); + const started = Date.now(); + const response = await fetch(`http://127.0.0.1:${proxy.address().port}/api/uptime/speed-test`, { + method: 'POST', body: '{}', headers: { 'content-type': 'application/json' }, signal: AbortSignal.timeout(60_000), + }); + assert.equal(response.status, 502, 'Next must preserve the backend failure receipt after 30s'); + assert.deepEqual(await response.json(), { error: 'Backend timeout receipt', outcome: 'unknown' }); + assert(Date.now() - started >= 31_000); + console.log('Next proxy: delayed 502 JSON preserved beyond 30s'); + } finally { + for (const timer of pending) clearTimeout(timer); + proxy.closeAllConnections(); backend.closeAllConnections(); + await Promise.all([proxy, backend].map(server => new Promise(resolve => server.close(resolve)))); + } +})().catch(error => { console.error(error.message); process.exitCode = 1; });