diff --git a/app/(main)/uptime/page.tsx b/app/(main)/uptime/page.tsx
index 5fc62d04..57c6a018 100644
--- a/app/(main)/uptime/page.tsx
+++ b/app/(main)/uptime/page.tsx
@@ -1664,12 +1664,12 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
lines.push("")
if (si) {
- lines.push(`/ip address print where name="${si.replace(/"/g, '\\"')}"`)
+ lines.push(`/ip address print where interface="${si.replace(/"/g, '\\"')}"`)
lines.push("")
}
if (di) {
lines.push(`# Выполнить на узле назначения (${dst.name}) — адрес приёмника BT-сервера:`)
- lines.push(`/ip address print where name="${di.replace(/"/g, '\\"')}"`)
+ lines.push(`/ip address print where interface="${di.replace(/"/g, '\\"')}"`)
lines.push("")
}
@@ -2778,6 +2778,11 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
/>
+
+ Интерфейс источника используется для Ping после теста. На назначении выбирается
+ IP интерфейса, статический — первым. Маршрут bandwidth-test определяет RouterOS.
+
+
=400, HTTP-моков нет. Temporaryfrontend/backend/network/3018 закрыты, destinationhost восстановлен и проверен, testprobes0; основной стенд/туннель сохранены.
Локальная regression31s/TypeScript/ESLint12.5.26 и real production browser proof подтверждают исправление proxy. ROS-2 transport timeout принят в этих границах; native can not connect/busy/disconnect/abort и Portal/multi-instance остаются открытыми. Следующий12.5.28 — ROS-3: фактический адрес native bandwidth-test и интерфейс after-ping. План/паспорт/протокол обновлены; локальный коммит без push.
+
+## 12.5.28 — интерфейс bandwidth-test и after-ping; уточнение формы (2026-10-08)
+
+[Real native/API/SQL evidence](ux-ui/acceptance/speed-interface-2026-10-08.json): backend8782054, выделенная mmapp_acceptance_20261007; реальные inventory и команды, HTTP/RouterOS-моков нет. На обоих CHR активны ether1/lo. НаCHR1 ether1 имеет dynamic194.226.121.150/24; наCHR2 dynamic104.165.244.7/24 иstatic195.195.195.195/32. Существующая конфигурация RouterOS не менялась. API каталога предпочитает static195 при явном выборе ether1 назначения. Это не тот же адрес, что host/API104.
+
+Три попытки1→2 (дважды с выбранным ether1 назначения, один разauto) получили502/transport timeout и historyerror; никакая из них не объявлена успешной. Bandwidth-server enabledtrue/authenticatetrue/maxsessions100 наобоихCHR, Ping1→2 и2→1 поether1 подтвердил2/2/0%loss. Причина timeout1→2/auto не установлена. Нельзя заключать, что её вызвала ошибка приложения или исключительноstaticадрес.
+
+Отдельная принятая команда2→1: srcInterfaceether1, dstInterfaceauto, TCPtransmit3s/HTTP200. Wrapper считал и записывал только несекретные параметры настоящих вызовов: bandwidth address194.226.121.150 без interface-параметра; after-ping addressтотже/count4/interfaceether1/interval1s. API/SQLhistorydone, TX3756.788128/RXnull, Ping53ms/0%loss. srcInterfaceAddress195 — metadata выбранного интерфейса, не доказательство фактического source IP bandwidth packets. Native routing определяет RouterOS; source-interface binding не реализован. В принятом прогоне native1, всего4 команды с учётом трёх непрошедшихforward-прогонов. Это функциональная проверка, не benchmark/multi-WAN proof.
+
+В форме локально добавлено пояснение: интерфейс источника используется для Ping после теста, интерфейс назначения выбираетIP/staticfirst, маршрутbandwidth-test определяетRouterOS. Исправлена CLI-подсказка /ip address print where interface= вместоwhere name=; [синтаксис RouterOS](https://help.mikrotik.com/docs/spaces/ROS/pages/47579229/Scripting). Установленные ReUI/Frame-композиции сохранены, новый компонент не устанавливался.
+
+Проверки локального UI: uptime-speed-interface.spec.ts1/1 сHTTP-фикстурами — открытие формы, приоритет адреса изAPI, корректныйCLI/Ping, пояснение и320px fits; scopedfrontend TypeScript/ESLint passed. Это локальная проверка формы, не realbrowserproof новых текстов. Runtimefrontendaa7dbdf прежний, новыеUIизменения ещё не развёрнуты.
+
+Временные --rm containers закрыты, testprobes0; история тестов только в выделеннойБД, основнаяhistory5/backend8782054healthok сохранены. ROS-3 принят дляобратнойкоманды в перечисленных границах; forward2interface/auto не принят. Следующий12.5.29 — realbrowserform/deploymentподсказок; forward-native диагностика иполный12.5 остаются открытыми. План/паспорт/протокол обновлены, локальный коммит без push.
diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md
index 81f427f1..e96fa018 100644
--- a/docs/ux-ui-test-server.md
+++ b/docs/ux-ui-test-server.md
@@ -157,3 +157,7 @@ ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 root@161.104.46.222
## Новый frontend proxy timeout — 2026-10-08
12.5.27 [real browser timeout502](ux-ui/acceptance/speed-unreachable-error-2026-10-08.json), [frontend deployment](ux-ui/acceptance/deployed-frontend-aa7dbdf-2026-10-08.json), [пять экранов](ux-ui/acceptance/deploy-browser-aa7dbdf-2026-10-08.json) passed. Frontendaa7dbdf/proxy180s, backend8782054healthy прежний; MMAPP_IMAGE_TAG=ux-aa7dbdf/BACKEND_IMAGE_TAG=ux-8782054. Основной DBcontrol совпал. Isolatedhost/probe восстановлены/удалены, temporarycontainers/network/3018 закрыты. Это transport timeout, не native can not connect; техническая подпись timeout остаётся ограничением UX. Следующий12.5.28 — ROS-3 interface/address/after-ping.
+
+## Интерфейс native test и Ping — 2026-10-08
+
+12.5.28 [real ROS-3](ux-ui/acceptance/speed-interface-2026-10-08.json): reverse2→1 done, bandwidth194.226.121.150/nointerfacebinding, Pingether1/0%loss; metadata source195 не доказываетsourceIPpackets. CHR2 имеет dynamic104/static195, явныйdstinterface предпочитаетstatic. Три1→2 попыткиtimeout, причинаauto-path не установлена; они не приняты. КонфигурацияRouterOS не менялась. Основнойruntimebackend8782054/frontendaa7dbdf/history5 сохранён. UIhint/CLIwhereinterface исправлены локально; browserfixture/typecheck/ESLint passed, не развёрнуты. Следующий12.5.29 — real browserform/deploymentподсказок.
diff --git a/docs/ux-ui/acceptance/speed-interface-2026-10-08.json b/docs/ux-ui/acceptance/speed-interface-2026-10-08.json
new file mode 100644
index 00000000..3e02e84d
--- /dev/null
+++ b/docs/ux-ui/acceptance/speed-interface-2026-10-08.json
@@ -0,0 +1,138 @@
+{
+ "date": "2026-10-08",
+ "backendSource": "8782054078304f36cc611876af2d17f87b857f60",
+ "database": "mmapp_acceptance_20261007",
+ "httpMocks": false,
+ "routerOsMocks": false,
+ "inventory": [
+ {
+ "id": 1,
+ "host": "194.226.121.150",
+ "interfaces": [
+ "ether1",
+ "lo"
+ ],
+ "addresses": [
+ {
+ "interface": "ether1",
+ "address": "194.226.121.150/24",
+ "dynamic": "true"
+ }
+ ]
+ },
+ {
+ "id": 2,
+ "host": "104.165.244.7",
+ "interfaces": [
+ "ether1",
+ "lo"
+ ],
+ "addresses": [
+ {
+ "interface": "ether1",
+ "address": "104.165.244.7/24",
+ "dynamic": "true"
+ },
+ {
+ "interface": "ether1",
+ "address": "195.195.195.195/32",
+ "dynamic": "false"
+ }
+ ]
+ }
+ ],
+ "selectedDestination": {
+ "preferredStaticAddress": "195.195.195.195",
+ "earlierForwardTests": "timeout"
+ },
+ "httpStatus": 200,
+ "nativeCount": 1,
+ "bandwidth": {
+ "address": "194.226.121.150",
+ "protocol": "tcp",
+ "direction": "transmit",
+ "durationSec": 3,
+ "hasInterfaceParameter": false
+ },
+ "pingCalls": [
+ {
+ "address": "194.226.121.150",
+ "count": 4,
+ "interface": "ether1",
+ "interval": "1s"
+ }
+ ],
+ "result": {
+ "runId": "acceptance-interface-1791428239785",
+ "srcInterfaceAddress": "195.195.195.195",
+ "dstInterfaceAddress": null,
+ "afterBtPing": {
+ "rttMs": 53,
+ "lossPct": 0,
+ "error": null
+ }
+ },
+ "history": [
+ {
+ "id": "acceptance-interface-1791428239785",
+ "src_interface": "ether1",
+ "dst_interface": "",
+ "src_interface_address": "195.195.195.195",
+ "dst_interface_address": null,
+ "status": "done",
+ "tx_avg_mbps": 3756.7881279999997,
+ "rx_avg_mbps": null,
+ "ping_rtt_ms": 53,
+ "ping_loss_pct": 0
+ }
+ ],
+ "limits": [
+ "Bandwidth routing chosen by RouterOS, no source-interface binding",
+ "One actual interface per CHR; multi-WAN route selection not tested",
+ "Accepted reverse command1; three earlier forward attempts timed out, forward path remains unaccepted",
+ "API/SQL/native proof; browser form not tested in this block"
+ ],
+ "firstInventoryAddresses": [
+ {
+ "interface": "ether1",
+ "address": "194.226.121.150"
+ },
+ {
+ "interface": "ether1",
+ "address": "104.165.244.7"
+ }
+ ],
+ "acceptedContext": {
+ "srcServerId": 2,
+ "dstServerId": 1,
+ "srcInterface": "ether1",
+ "dstInterface": "auto"
+ },
+ "forwardAttempts": [
+ {
+ "id": "acceptance-interface-1791427768086",
+ "srcInterface": "ether1",
+ "dstInterface": "ether1",
+ "status": "error"
+ },
+ {
+ "id": "acceptance-selected-destination-1791428012326",
+ "srcInterface": "ether1",
+ "dstInterface": "ether1",
+ "status": "error"
+ },
+ {
+ "id": "acceptance-interface-1791428042466",
+ "srcInterface": "ether1",
+ "dstInterface": "auto",
+ "status": "error"
+ }
+ ],
+ "cleanup": {
+ "testProbesRemaining": 0,
+ "temporaryContainersRemoved": true,
+ "mainHistoryCountUnchanged": 5,
+ "mainHealth": "ok",
+ "mainBackendVersion": "1.0.0-test.8782054"
+ }
+}
diff --git a/tests/e2e/uptime-speed-interface.spec.ts b/tests/e2e/uptime-speed-interface.spec.ts
new file mode 100644
index 00000000..a3daa4d3
--- /dev/null
+++ b/tests/e2e/uptime-speed-interface.spec.ts
@@ -0,0 +1,30 @@
+import { test, expect } from "@playwright/test"
+import { server } from "./fixtures/users"
+
+test("Speed: форма использует адрес каталога и разделяет маршрут теста и Ping-интерфейс", async ({ page }) => {
+ const probe = { id: "iface-probe", srcServerId: "1", dstServerId: "2", srcInterface: "ether1", dstInterface: "ether1", protocol: "tcp", direction: "transmit", durationSec: "3", enabled: true, lastRunAt: null, lastStatus: null, lastError: null, lastTxAvgMbps: null, lastRxAvgMbps: null }
+ await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
+ await page.route("**/api/**", route => {
+ const path = new URL(route.request().url()).pathname
+ return route.fulfill({ json:
+ path === "/api/auth/config" ? { required: false } :
+ path === "/api/servers" ? [server, { ...server, id: 2, name: "Назначение", host: "198.51.100.2" }] :
+ path === "/api/uptime/overview" ? { probes: [], resources: [] } :
+ path === "/api/uptime/speed-probes" ? { probes: [probe] } :
+ path === "/api/uptime/speed-test/runs" ? { runs: [] } :
+ path.includes("/speed-test/endpoints/") ? { interfaces: [{ name: "ether1", running: true, disabled: false, addresses: path.includes("/2/") ? ["195.195.195.195", "198.51.100.2"] : ["192.0.2.1"] }] } : {},
+ })
+ })
+ await page.goto("/uptime?tab=speed")
+ await page.getByRole("button", { name: "Редактировать speed-пробу", exact: true }).click()
+ const dialog = page.getByRole("dialog")
+ const commands = dialog.locator("pre")
+ await expect(commands).toContainText('/ip address print where interface="ether1"')
+ await expect(commands).not.toContainText("where name=")
+ await expect(commands).toContainText('/ping address=195.195.195.195 count=4 interface="ether1"')
+ await expect(commands).toContainText("/tool bandwidth-test address=195.195.195.195")
+ await expect(dialog).toContainText("Интерфейс источника используется для Ping после теста")
+ await expect(dialog).toContainText("Маршрут bandwidth-test определяет RouterOS")
+ await page.setViewportSize({ width: 320, height: 900 })
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
+})