From 9c4a0992d79c0acdb3c836515326ef789742ddc7 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Wed, 14 Oct 2026 01:16:19 +0700 Subject: [PATCH] =?UTF-8?q?fix(alerts):=20=D1=83=D1=87=D0=B8=D1=82=D1=8B?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=80=D0=B5=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=B0=20GRE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 2 +- .../acceptance/gre-complete-source-sql.mjs | 24 ++++++ backend/src/services/gre-tunnels-live.test.ts | 14 ++++ backend/src/services/gre-tunnels-live.ts | 32 ++++--- docs/ux-ui-external-acceptance.md | 6 +- docs/ux-ui-plan.md | 2 +- docs/ux-ui-progress.md | 12 ++- docs/ux-ui-remaining-acceptance.md | 10 ++- docs/ux-ui-stage-12.md | 13 ++- docs/ux-ui-test-server.md | 6 +- docs/ux-ui/acceptance/gre219-baseline.json | 83 +++++++++++++++++++ .../gre219-build-proof-2026-10-14.json | 22 +++++ .../gre219-deployment-2026-10-14.json | 21 +++++ docs/ux-ui/acceptance/gre219-fixed.json | 83 +++++++++++++++++++ .../gre219-native-live-2026-10-14.json | 62 ++++++++++++++ 15 files changed, 370 insertions(+), 22 deletions(-) create mode 100644 backend/scripts/acceptance/gre-complete-source-sql.mjs create mode 100644 backend/src/services/gre-tunnels-live.test.ts create mode 100644 docs/ux-ui/acceptance/gre219-baseline.json create mode 100644 docs/ux-ui/acceptance/gre219-build-proof-2026-10-14.json create mode 100644 docs/ux-ui/acceptance/gre219-deployment-2026-10-14.json create mode 100644 docs/ux-ui/acceptance/gre219-fixed.json create mode 100644 docs/ux-ui/acceptance/gre219-native-live-2026-10-14.json diff --git a/backend/package.json b/backend/package.json index 55e0b763..57e96ddd 100644 --- a/backend/package.json +++ b/backend/package.json @@ -8,7 +8,7 @@ "dev": "tsx watch src/index.ts", "build": "npm run build -w @mmapp/contracts && tsc", "test:alerts-telegram": "tsx src/services/alerts-outbox-retry.test.ts && tsx src/services/alerts-outbox-overview.test.ts && tsx src/services/alert-engine/outbox-execution.test.ts && tsx src/services/alerts-telegram-delivery.test.ts && tsx src/services/alerts-revision.test.ts && tsx src/services/alerts-overview.test.ts && tsx ../packages/contracts/src/alerts-normalization.test.ts && tsx src/services/alerts-config-execution.test.ts && tsx src/services/alerts-telegram-settings.test.ts && tsx src/services/alerts-telegram-send.test.ts && tsx src/routes/alerts.test.ts && tsx src/plugins/auth.alerts.test.ts", - "test:alert-engine": "tsx src/services/alert-engine/server-signal-identity.test.ts && tsx src/services/alert-engine/collector-source-signals.test.ts && tsx src/services/alert-engine/monitoring-history.test.ts && tsx src/services/alert-engine/groups.test.ts && tsx src/services/alert-engine/evaluate-rule.test.ts && tsx src/services/bgp-peers-live.test.ts && tsx src/services/gre-bgp-snapshot-collector.test.ts && tsx src/services/gre-bgp-snapshot-history.test.ts && tsx src/services/gre-bgp-snapshot-sql.test.ts && tsx src/services/alert-engine/collector-source-sql.test.ts && tsx src/services/alert-engine/confirm-stability.test.ts", + "test:alert-engine": "tsx src/services/alert-engine/server-signal-identity.test.ts && tsx src/services/alert-engine/collector-source-signals.test.ts && tsx src/services/alert-engine/monitoring-history.test.ts && tsx src/services/alert-engine/groups.test.ts && tsx src/services/alert-engine/evaluate-rule.test.ts && tsx src/services/gre-tunnels-live.test.ts && tsx src/services/bgp-peers-live.test.ts && tsx src/services/gre-bgp-snapshot-collector.test.ts && tsx src/services/gre-bgp-snapshot-history.test.ts && tsx src/services/gre-bgp-snapshot-sql.test.ts && tsx src/services/alert-engine/collector-source-sql.test.ts && tsx src/services/alert-engine/confirm-stability.test.ts", "start": "node dist/index.js", "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate", diff --git a/backend/scripts/acceptance/gre-complete-source-sql.mjs b/backend/scripts/acceptance/gre-complete-source-sql.mjs new file mode 100644 index 00000000..9940d3ac --- /dev/null +++ b/backend/scripts/acceptance/gre-complete-source-sql.mjs @@ -0,0 +1,24 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import {createServer} from 'node:http' +const database=process.env.MMAPP_OWN_SQL_DB,url=new URL(process.env.DATABASE_URL) +assert(/^mm_accept_166_\d+$/.test(database??''));assert.equal(url.pathname,'/'+database);assert.equal(url.username,database) +const {pool,closePool}=await import('/app/backend/dist/db/index.js'),{initDatabase}=await import('/app/backend/dist/db/bootstrap.js'),{collectGreBgpSnapshotOnce}=await import('/app/backend/dist/services/gre-bgp-snapshot-collector.js') +assert.equal((await pool.query('SELECT current_database() AS name')).rows[0].name,database);assert(Object.values((await pool.query('SELECT rolsuper,rolcreatedb,rolcreaterole,rolbypassrls FROM pg_roles WHERE rolname=current_user')).rows[0]).every(v=>v===false)) +const baseline=process.env.MMAPP_BASELINE==='true',cases=[];let phase='populated',nativeCalls=0,nativeWrites=0,disabledCalls=0 +const fixture=label=>createServer((req,res)=>{nativeCalls++;if(label==='disabled')disabledCalls++;if(req.method!=='GET')nativeWrites++;res.setHeader('content-type','application/json');const gre=req.url==='/rest/interface/gre',failed=(gre&&phase==='gre-failed')||(label==='second'&&(gre&&['gre-partial','both-partial'].includes(phase)||!gre&&['bgp-partial','both-partial'].includes(phase)));if(failed){res.statusCode=401;res.end(JSON.stringify({error:401,message:'own219 denied'}));return}const row=gre?{'.id':'*1',name:'own219-gre',running:'true',disabled:'false'}:{'.id':'*1',name:'own219-peer',established:'true','remote.as':'65219','local.as':'65220'};const rows=phase==='empty'?[]:gre&&label==='second'&&phase==='malformed'?[{unknown:'fixture'}]:gre&&label==='second'&&phase==='duplicate'?[row,row]:[row];res.end(JSON.stringify(rows))}) +const natives=['first','second','disabled'].map(fixture);for(const n of natives)await new Promise(r=>n.listen(0,'127.0.0.1',r)) +const report={date:'2026-10-14',block:'12.5.219',baseline,database,cases,scope:'Actual compiled GRE/BGP sources and snapshot collector, owned SQL/native HTTP fixture; no API auth claim',passed:false} +try{ + await initDatabase();for(let i=0;ie.startsWith('GRE: Не опрошены устройства GRE:'))) + if(bgpFail)assert(snapshot.errors.some(e=>e.startsWith('BGP: Не опрошены устройства BGP:'))) + if(phase==='disabled')assert.equal(nativeCalls,before) + cases.push({phase,greWritten:snapshot.greWritten,bgpWritten:snapshot.bgpWritten,sourceErrors:snapshot.errors.length,nativeCalls:nativeCalls-before}) + } + assert.equal(nativeWrites,0);assert.equal(disabledCalls,0);report.passed=true +}catch(e){report.errorName=e.name;fs.writeFileSync('/app/backend/acceptance/gre219-private.log',String(e.stack??e),{mode:0o600})}finally{for(const n of natives){n.closeAllConnections();await new Promise(r=>n.close(r))}await closePool();report.nativeWrites=nativeWrites;report.disabledHomeRouterCalls=disabledCalls;fs.writeFileSync('/app/backend/acceptance/gre219-'+(baseline?'baseline':'fixed')+'.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report))}if(!report.passed)process.exitCode=1 diff --git a/backend/src/services/gre-tunnels-live.test.ts b/backend/src/services/gre-tunnels-live.test.ts new file mode 100644 index 00000000..9845929d --- /dev/null +++ b/backend/src/services/gre-tunnels-live.test.ts @@ -0,0 +1,14 @@ +import assert from 'node:assert/strict' +import {fetchGreTunnelLiveRows} from './gre-tunnels-live.js' +import {collectGreBgpSnapshotOnce} from './gre-bgp-snapshot-collector.js' +import {servers} from '../db/schema.js' +const devices=[{id:1,name:'Первый'},{id:2,name:'Второй'}] as typeof servers.$inferSelect[] +for(const phase of ['populated','empty','partial','failed','disabled','sync-failed'] as const){ + let calls=0 + const deps={listEnabledServers:async()=>phase==='disabled'?[]:devices,readTunnels:(server:typeof servers.$inferSelect)=>{calls++;if(phase==='sync-failed')throw Error('sync denied');return (async()=>{if(phase==='failed'||(phase==='partial'&&server.id===2))throw Error('native401');return phase==='populated'?[{targetLabel:'Own GRE / '+server.name,status:'up' as const}]:[]})()}} + const result=await collectGreBgpSnapshotOnce({fetchGre:()=>fetchGreTunnelLiveRows(deps),fetchBgp:async()=>[{serverName:'BGP-control',name:'own-peer',state:'Established'}]}) + assert.equal(result.bgpWritten,1);assert.equal(result.greWritten,phase==='populated'?2:0);assert.equal(result.errors.length,['partial','failed','sync-failed'].includes(phase)?1:0) + if(result.errors.length){assert.match(result.errors[0],/GRE: Не опрошены устройства GRE/);assert.match(result.errors[0],/Второй/);if(phase!=='partial')assert.match(result.errors[0],/Первый/)} + if(phase==='disabled')assert.equal(calls,0) +} +console.log('GRE alert source: populated/empty/partial/all-failed/disabled/sync error; BGP control preserved, per-device errors retained') diff --git a/backend/src/services/gre-tunnels-live.ts b/backend/src/services/gre-tunnels-live.ts index 7103668a..98acd913 100644 --- a/backend/src/services/gre-tunnels-live.ts +++ b/backend/src/services/gre-tunnels-live.ts @@ -2,6 +2,7 @@ import { eq } from "drizzle-orm" import { db } from "../db/index.js" import { servers } from "../db/schema.js" import { MikrotikClient } from "./mikrotik.js" +import { readInternetPathRows } from "./internet-path-snapshot.js" type ServerRow = typeof servers.$inferSelect @@ -40,21 +41,26 @@ function mapGreRow(server: ServerRow, g: RosGre, idx: number): GreTunnelLiveRow async function fetchGreForServer(server: ServerRow): Promise { const client = MikrotikClient.fromServer(server) - const greRaw = await client.get("/interface/gre") + const greRaw = readInternetPathRows(await client.get("/interface/gre"), "GRE alert source", [".id", "name"]) + if (new Set(greRaw.map(row => row[".id"])).size !== greRaw.length) throw new Error("Повторяющиеся ID GRE") return greRaw.map((g, idx) => mapGreRow(server, g, idx)) } +interface GreAlertDependencies { + listEnabledServers: () => Promise + readTunnels: (server: ServerRow) => Promise +} +const alertDefaults: GreAlertDependencies = { + listEnabledServers: () => db.select().from(servers).where(eq(servers.enabled, true)), + readTunnels: fetchGreForServer, +} + /** GRE с включённых серверов — тот же смысл, что `/api/filters/gre-tunnels` (без правил фильтров). */ -export async function fetchGreTunnelLiveRows(): Promise { - const enabledServers = await db.select().from(servers).where(eq(servers.enabled, true)) - const results = await Promise.all( - enabledServers.map(async (server) => { - try { - return await fetchGreForServer(server) - } catch { - return [] as GreTunnelLiveRow[] - } - }), - ) - return results.flat() +export async function fetchGreTunnelLiveRows(dependencies: GreAlertDependencies = alertDefaults): Promise { + const devices = await dependencies.listEnabledServers() + const results = await Promise.allSettled(devices.map(server => Promise.resolve().then(() => dependencies.readTunnels(server)))) + const failures = results.flatMap((result, index) => result.status === "rejected" + ? [`${devices[index].name}: ${result.reason instanceof Error ? result.reason.message : "Ошибка опроса устройства"}`] : []) + if (failures.length) throw new Error("Не опрошены устройства GRE: " + failures.join("; ")) + return results.flatMap(result => result.status === "fulfilled" ? result.value : []) } diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index c783867b..f66c368b 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -1,6 +1,6 @@ # UX/UI: протокол внешней приёмки 12.5 -Актуальное продолжение 2026-10-14: блок218 завершён. Заполненные BGP state/type/prefix RX и OSPF route type переведены на читаемые ReUI Badge/основной цвет чисел. Baseline22 violations; fixed104 scoped cells0, E2E22, TypeScript/ESLint/build прошли. Own GRE/OSPF/BGP поднялись, UI8 прошли, own objects удалены и static projection10×2 совпал. Frontend ux-routing218/source527 matched, backend ux-wan217. Следующий219 — скрытые ошибки GRE source snapshots для оповещений. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: блок219 завершён. GRE source snapshots больше не подавляет per-device ошибки; повреждённые records/duplicate native IDs отклоняются. BGP observations сохраняются при GRE failure. Четыре профиля, SQL/native10, compiled actual source2own GRE и UI1440/320 прошли; own DB/roles/tunnels удалены. Backend ux-gre219/compiled1052/source486 matched, frontend ux-routing218. Следующий220 — неизвестные/некорректные GRE operational flags в snapshots. Этап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). @@ -2599,3 +2599,7 @@ Read failures/malformed collections дают502, выключенные устр ## 12.5.218 — заполненные routing tables (2026-10-14) BGP/OSPF contrast: baseline22/fixed104 cells0 violations; E2E22 и real UI8 passed. Own GRE/OSPF/BGP objects удалены; статическая сверка10×2 прошла. Подробности и границы — [журнал](ux-ui-progress.md). Frontend ux-routing218, backend ux-wan217; следующий219 — GRE snapshot source errors. + +## 12.5.219 — GRE snapshot source (2026-10-14) + +Ошибки GRE source отражаются в snapshot; BGP при GRE failure сохраняется. SQL/native10 и actual compiled source2own GRE/UI passed; временные объекты удалены. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-gre219, frontend ux-routing218; следующий220 — неизвестные GRE flags. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 76ba8be1..c6562d12 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,6 +1,6 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-14: блок218 завершён. Заполненные BGP state/type/prefix RX и OSPF route type переведены на читаемые ReUI Badge/основной цвет чисел. Baseline22 violations; fixed104 scoped cells0, E2E22, TypeScript/ESLint/build прошли. Own GRE/OSPF/BGP поднялись, UI8 прошли, own objects удалены и static projection10×2 совпал. Frontend ux-routing218/source527 matched, backend ux-wan217. Следующий219 — скрытые ошибки GRE source snapshots для оповещений. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: блок219 завершён. GRE source snapshots больше не подавляет per-device ошибки; повреждённые records/duplicate native IDs отклоняются. BGP observations сохраняются при GRE failure. Четыре профиля, SQL/native10, compiled actual source2own GRE и UI1440/320 прошли; own DB/roles/tunnels удалены. Backend ux-gre219/compiled1052/source486 matched, frontend ux-routing218. Следующий220 — неизвестные/некорректные GRE operational flags в snapshots. Этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-13. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index a51a2910..49dd7268 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-14: блок218 завершён. Заполненные BGP state/type/prefix RX и OSPF route type переведены на читаемые ReUI Badge/основной цвет чисел. Baseline22 violations; fixed104 scoped cells0, E2E22, TypeScript/ESLint/build прошли. Own GRE/OSPF/BGP поднялись, UI8 прошли, own objects удалены и static projection10×2 совпал. Frontend ux-routing218/source527 matched, backend ux-wan217. Следующий219 — скрытые ошибки GRE source snapshots для оповещений. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: блок219 завершён. GRE source snapshots больше не подавляет per-device ошибки; повреждённые records/duplicate native IDs отклоняются. BGP observations сохраняются при GRE failure. Четыре профиля, SQL/native10, compiled actual source2own GRE и UI1440/320 прошли; own DB/roles/tunnels удалены. Backend ux-gre219/compiled1052/source486 matched, frontend ux-routing218. Следующий220 — неизвестные/некорректные GRE operational flags в snapshots. Этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -38,6 +38,16 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–196 и ограничения ниже. Runtime backend/frontend ux-peak196. | +## 12.5.219 — ошибки реального GRE source для snapshots (2026-10-14) + +fetchGreTunnelLiveRows подавлял native failures через[] и collector принимал пустой/неполный источник без ошибки. Теперь per-device reads settled независимо, все ошибки агрегируются по устройствам и неполный источник отклоняется; collector записывает GRE source error и сохраняет независимо прочитанный BGP. Raw GRE должен быть корректной коллекцией string records с native .id/name; duplicate IDs отклоняются. Правила сигналов/доставки и существующая трактовка running/disabled пока не менялись: неизвестные operational flags — следующий220. + +Четыре профильных скрипта и build прошли. Baseline ux-wan217 и fixed ux-gre219: по10 production SQL/native-fixture случаев populated/empty/GRE partial/all failed/BGP partial/both partial/malformed/duplicate/disabled/recovery. Baseline принял повреждённые и duplicate записи без source error; fixed отмечает неполный GRE observation, BGP control сохраняется. Native writes0, disabled Home Router calls0; own DB/roles удалены. + +Backend ux-gre219 compiled1052/source486 matched, healthy; frontend ux-routing218 сохранён. Через настоящий Portal API созданы own disabled GRE2. Native disabled=true/running=false, application status=down. Actual compiled collectGreBgpSnapshotOnce в отдельном read-only процессе контейнера прочитал lab PostgreSQL/native и дал две own down rows, sourceErrors0; scheduler history не записывался, это не auth test самого collector. GRE UI1440/320 увидел own rows без page errors/mutations. Туннели удалены, absence native/API проверен, пароли не менялись; Telegram не отправлялся. Полный durable alert delivery и physical fault этим блоком не принимаются. + +Протоколы: [baseline](ux-ui/acceptance/gre219-baseline.json), [fixed](ux-ui/acceptance/gre219-fixed.json), [build](ux-ui/acceptance/gre219-build-proof-2026-10-14.json), [deployment](ux-ui/acceptance/gre219-deployment-2026-10-14.json), [native source/UI/cleanup](ux-ui/acceptance/gre219-native-live-2026-10-14.json). Следующий220 — не подтверждать degraded/up/down по отсутствующим/повреждённым GRE flags; валидные native состояния сохранить. + ## 12.5.218 — контраст заполненных BGP и OSPF таблиц (2026-10-14) Baseline104 explicitly scrolled cell checks:22 нарушений в light на1440/320. BGP Established3,31:1, Active2,96:1, Idle4,21:1, prefix RX3,65:1; OSPF O E2 3,23:1. Ручные state/type spans заменены штатным ReUI Badge invert-light; BGP состояния дополнительно различаются семантическим индикатором и прежним текстом. Protocol type — текстовая категория без оценки здоровья. Prefix RX читает основной цвет. OSPF type Badge общий для строк, counts и легенды; vendor components/theme не менялись. diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index 5ec89819..0a6c7f72 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,10 +1,10 @@ # Оставшаяся внешняя приёмка — 2026-10-13 -Актуальное продолжение 2026-10-14: блок218 завершён. Заполненные BGP state/type/prefix RX и OSPF route type переведены на читаемые ReUI Badge/основной цвет чисел. Baseline22 violations; fixed104 scoped cells0, E2E22, TypeScript/ESLint/build прошли. Own GRE/OSPF/BGP поднялись, UI8 прошли, own objects удалены и static projection10×2 совпал. Frontend ux-routing218/source527 matched, backend ux-wan217. Следующий219 — скрытые ошибки GRE source snapshots для оповещений. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: блок219 завершён. GRE source snapshots больше не подавляет per-device ошибки; повреждённые records/duplicate native IDs отклоняются. BGP observations сохраняются при GRE failure. Четыре профиля, SQL/native10, compiled actual source2own GRE и UI1440/320 прошли; own DB/roles/tunnels удалены. Backend ux-gre219/compiled1052/source486 matched, frontend ux-routing218. Следующий220 — неизвестные/некорректные GRE operational flags в snapshots. Этап12.5 открыт. -Это актуальная матрица после 12.5.218. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.219. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-wan217`, frontend `ux-routing218`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-gre219`, frontend `ux-routing218`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | @@ -1517,3 +1517,7 @@ Read failures/malformed collections дают502, выключенные устр ## 12.5.218 — заполненные routing tables (2026-10-14) BGP/OSPF contrast: baseline22/fixed104 cells0 violations; E2E22 и real UI8 passed. Own GRE/OSPF/BGP objects удалены; статическая сверка10×2 прошла. Подробности и границы — [журнал](ux-ui-progress.md). Frontend ux-routing218, backend ux-wan217; следующий219 — GRE snapshot source errors. + +## 12.5.219 — GRE snapshot source (2026-10-14) + +Ошибки GRE source отражаются в snapshot; BGP при GRE failure сохраняется. SQL/native10 и actual compiled source2own GRE/UI passed; временные объекты удалены. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-gre219, frontend ux-routing218; следующий220 — неизвестные GRE flags. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 264b4e02..5ec5f170 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-14: блок218 завершён. Заполненные BGP state/type/prefix RX и OSPF route type переведены на читаемые ReUI Badge/основной цвет чисел. Baseline22 violations; fixed104 scoped cells0, E2E22, TypeScript/ESLint/build прошли. Own GRE/OSPF/BGP поднялись, UI8 прошли, own objects удалены и static projection10×2 совпал. Frontend ux-routing218/source527 matched, backend ux-wan217. Следующий219 — скрытые ошибки GRE source snapshots для оповещений. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: блок219 завершён. GRE source snapshots больше не подавляет per-device ошибки; повреждённые records/duplicate native IDs отклоняются. BGP observations сохраняются при GRE failure. Четыре профиля, SQL/native10, compiled actual source2own GRE и UI1440/320 прошли; own DB/roles/tunnels удалены. Backend ux-gre219/compiled1052/source486 matched, frontend ux-routing218. Следующий220 — неизвестные/некорректные GRE operational flags в snapshots. Этап12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -3967,3 +3967,14 @@ Fixed104 scoped cells0 violations, E2E22 (8 contrast fixtures + BGP data13 + OSP Протоколы: [contrast](ux-ui/acceptance/routing218-contrast-2026-10-14.json), [source](ux-ui/acceptance/routing218-source-proof-2026-10-14.json), [deployment](ux-ui/acceptance/routing218-deployment-2026-10-14.json), [storage cleanup](ux-ui/acceptance/routing218-storage-cleanup.json), [native/UI/cleanup](ux-ui/acceptance/routing218-native-live-2026-10-14.json). Следующий219 — GRE источник snapshots: сейчас fetchGreTunnelLiveRows подавляет ошибки устройств и сообщает успешный пустой результат. + +## 12.5.219 — ошибки реального GRE source для snapshots (2026-10-14) + +fetchGreTunnelLiveRows подавлял native failures через[] и collector принимал пустой/неполный источник без ошибки. Теперь per-device reads settled независимо, все ошибки агрегируются по устройствам и неполный источник отклоняется; collector записывает GRE source error и сохраняет независимо прочитанный BGP. Raw GRE должен быть корректной коллекцией string records с native .id/name; duplicate IDs отклоняются. Правила сигналов/доставки и существующая трактовка running/disabled пока не менялись: неизвестные operational flags — следующий220. + +Четыре профильных скрипта и build прошли. Baseline ux-wan217 и fixed ux-gre219: по10 production SQL/native-fixture случаев populated/empty/GRE partial/all failed/BGP partial/both partial/malformed/duplicate/disabled/recovery. Baseline принял повреждённые и duplicate записи без source error; fixed отмечает неполный GRE observation, BGP control сохраняется. Native writes0, disabled Home Router calls0; own DB/roles удалены. + +Backend ux-gre219 compiled1052/source486 matched, healthy; frontend ux-routing218 сохранён. Через настоящий Portal API созданы own disabled GRE2. Native disabled=true/running=false, application status=down. Actual compiled collectGreBgpSnapshotOnce в отдельном read-only процессе контейнера прочитал lab PostgreSQL/native и дал две own down rows, sourceErrors0; scheduler history не записывался, это не auth test самого collector. GRE UI1440/320 увидел own rows без page errors/mutations. Туннели удалены, absence native/API проверен, пароли не менялись; Telegram не отправлялся. Полный durable alert delivery и physical fault этим блоком не принимаются. + +Протоколы: [baseline](ux-ui/acceptance/gre219-baseline.json), [fixed](ux-ui/acceptance/gre219-fixed.json), [build](ux-ui/acceptance/gre219-build-proof-2026-10-14.json), [deployment](ux-ui/acceptance/gre219-deployment-2026-10-14.json), [native source/UI/cleanup](ux-ui/acceptance/gre219-native-live-2026-10-14.json). Следующий220 — не подтверждать degraded/up/down по отсутствующим/повреждённым GRE flags; валидные native состояния сохранить. + diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 5a512b8c..9f1d9779 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-10 -Актуальное продолжение 2026-10-14: блок218 завершён. Заполненные BGP state/type/prefix RX и OSPF route type переведены на читаемые ReUI Badge/основной цвет чисел. Baseline22 violations; fixed104 scoped cells0, E2E22, TypeScript/ESLint/build прошли. Own GRE/OSPF/BGP поднялись, UI8 прошли, own objects удалены и static projection10×2 совпал. Frontend ux-routing218/source527 matched, backend ux-wan217. Следующий219 — скрытые ошибки GRE source snapshots для оповещений. Этап12.5 открыт. +Актуальное продолжение 2026-10-14: блок219 завершён. GRE source snapshots больше не подавляет per-device ошибки; повреждённые records/duplicate native IDs отклоняются. BGP observations сохраняются при GRE failure. Четыре профиля, SQL/native10, compiled actual source2own GRE и UI1440/320 прошли; own DB/roles/tunnels удалены. Backend ux-gre219/compiled1052/source486 matched, frontend ux-routing218. Следующий220 — неизвестные/некорректные GRE operational flags в snapshots. Этап12.5 открыт. | Параметр | Проверенное состояние | | --- | --- | @@ -2330,3 +2330,7 @@ Read failures/malformed collections дают502, выключенные устр ## 12.5.218 — заполненные routing tables (2026-10-14) BGP/OSPF contrast: baseline22/fixed104 cells0 violations; E2E22 и real UI8 passed. Own GRE/OSPF/BGP objects удалены; статическая сверка10×2 прошла. Подробности и границы — [журнал](ux-ui-progress.md). Frontend ux-routing218, backend ux-wan217; следующий219 — GRE snapshot source errors. + +## 12.5.219 — GRE snapshot source (2026-10-14) + +Ошибки GRE source отражаются в snapshot; BGP при GRE failure сохраняется. SQL/native10 и actual compiled source2own GRE/UI passed; временные объекты удалены. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-gre219, frontend ux-routing218; следующий220 — неизвестные GRE flags. diff --git a/docs/ux-ui/acceptance/gre219-baseline.json b/docs/ux-ui/acceptance/gre219-baseline.json new file mode 100644 index 00000000..15992e32 --- /dev/null +++ b/docs/ux-ui/acceptance/gre219-baseline.json @@ -0,0 +1,83 @@ +{ + "date": "2026-10-14", + "block": "12.5.219", + "baseline": true, + "database": "mm_accept_166_1791915041693", + "cases": [ + { + "phase": "populated", + "greWritten": 2, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "empty", + "greWritten": 0, + "bgpWritten": 0, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "gre-partial", + "greWritten": 1, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "gre-failed", + "greWritten": 0, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "bgp-partial", + "greWritten": 2, + "bgpWritten": 0, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "both-partial", + "greWritten": 1, + "bgpWritten": 0, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "malformed", + "greWritten": 2, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "duplicate", + "greWritten": 3, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "disabled", + "greWritten": 0, + "bgpWritten": 0, + "sourceErrors": 0, + "nativeCalls": 0 + }, + { + "phase": "recovery", + "greWritten": 2, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + } + ], + "scope": "Actual compiled GRE/BGP sources and snapshot collector, owned SQL/native HTTP fixture; no API auth claim", + "passed": true, + "nativeWrites": 0, + "disabledHomeRouterCalls": 0, + "ownedDatabaseAndRoleRemoved": true +} diff --git a/docs/ux-ui/acceptance/gre219-build-proof-2026-10-14.json b/docs/ux-ui/acceptance/gre219-build-proof-2026-10-14.json new file mode 100644 index 00000000..b069223e --- /dev/null +++ b/docs/ux-ui/acceptance/gre219-build-proof-2026-10-14.json @@ -0,0 +1,22 @@ +{ + "date": "2026-10-14", + "block": "12.5.219", + "compiled": { + "matched": 1052, + "missing": 0, + "different": 0 + }, + "source": [ + { + "kind": "backend", + "matched": 486 + } + ], + "profileScripts": [ + "gre-tunnels-live", + "gre-bgp-snapshot-collector", + "gre-bgp-snapshot-history", + "collector-source-signals" + ], + "productionCases": 10 +} diff --git a/docs/ux-ui/acceptance/gre219-deployment-2026-10-14.json b/docs/ux-ui/acceptance/gre219-deployment-2026-10-14.json new file mode 100644 index 00000000..bb3fda53 --- /dev/null +++ b/docs/ux-ui/acceptance/gre219-deployment-2026-10-14.json @@ -0,0 +1,21 @@ +{ + "date": "2026-10-14", + "block": "12.5.219", + "backendSourceMatched": 486, + "compiledMatched": 1052, + "frontendChanged": false, + "services": { + "backend": { + "image": "mmapp-test/backend:ux-gre219", + "imageId": "sha256:c4938acbdb5c4c4b46d90f2ba356d673927b3a9a78fe4f44217089abbcfe9115", + "running": true, + "health": "healthy" + }, + "frontend": { + "image": "mmapp-test/frontend:ux-routing218", + "imageId": "sha256:ec658b9da88c19d60987be5bfc0c15fb339a0310d7a42dc761b40a70a3428c5a", + "running": true, + "health": null + } + } +} diff --git a/docs/ux-ui/acceptance/gre219-fixed.json b/docs/ux-ui/acceptance/gre219-fixed.json new file mode 100644 index 00000000..eee9a86b --- /dev/null +++ b/docs/ux-ui/acceptance/gre219-fixed.json @@ -0,0 +1,83 @@ +{ + "date": "2026-10-14", + "block": "12.5.219", + "baseline": false, + "database": "mm_accept_166_1791915166786", + "cases": [ + { + "phase": "populated", + "greWritten": 2, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "empty", + "greWritten": 0, + "bgpWritten": 0, + "sourceErrors": 0, + "nativeCalls": 4 + }, + { + "phase": "gre-partial", + "greWritten": 0, + "bgpWritten": 2, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "gre-failed", + "greWritten": 0, + "bgpWritten": 2, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "bgp-partial", + "greWritten": 2, + "bgpWritten": 0, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "both-partial", + "greWritten": 0, + "bgpWritten": 0, + "sourceErrors": 2, + "nativeCalls": 4 + }, + { + "phase": "malformed", + "greWritten": 0, + "bgpWritten": 2, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "duplicate", + "greWritten": 0, + "bgpWritten": 2, + "sourceErrors": 1, + "nativeCalls": 4 + }, + { + "phase": "disabled", + "greWritten": 0, + "bgpWritten": 0, + "sourceErrors": 0, + "nativeCalls": 0 + }, + { + "phase": "recovery", + "greWritten": 2, + "bgpWritten": 2, + "sourceErrors": 0, + "nativeCalls": 4 + } + ], + "scope": "Actual compiled GRE/BGP sources and snapshot collector, owned SQL/native HTTP fixture; no API auth claim", + "passed": true, + "nativeWrites": 0, + "disabledHomeRouterCalls": 0, + "ownedDatabaseAndRoleRemoved": true +} diff --git a/docs/ux-ui/acceptance/gre219-native-live-2026-10-14.json b/docs/ux-ui/acceptance/gre219-native-live-2026-10-14.json new file mode 100644 index 00000000..784ba2a7 --- /dev/null +++ b/docs/ux-ui/acceptance/gre219-native-live-2026-10-14.json @@ -0,0 +1,62 @@ +{ + "date": "2026-10-14", + "block": "12.5.219", + "backend": "ux-gre219", + "frontend": "ux-routing218", + "nativeCases": [ + { + "host": "194.226.121.150", + "nativeGetStatus": 200, + "applicationStatus": "down", + "nativeDisabled": "true", + "nativeRunning": "false", + "nativeIdPresent": true, + "nativeNamePresent": true + }, + { + "host": "104.165.244.7", + "nativeGetStatus": 200, + "applicationStatus": "down", + "nativeDisabled": "true", + "nativeRunning": "false", + "nativeIdPresent": true, + "nativeNamePresent": true + } + ], + "source": { + "date": "2026-10-14", + "name": "own219-gre-1791915208465", + "passed": true, + "mode": "Actual compiled helper reads lab PostgreSQL and native GRE/BGP; no scheduler history write", + "ownedGreRows": [ + { + "targetLabel": "own219-gre-1791915208465-1 / CHR", + "status": "down" + }, + { + "targetLabel": "own219-gre-1791915208465-2 / CHR", + "status": "down" + } + ], + "sourceErrors": 0 + }, + "ui": [ + { + "width": 1440, + "ownedNativeRowVisible": true, + "pageErrors": 0, + "mutationRequests": 0 + }, + { + "width": 320, + "ownedNativeRowVisible": true, + "pageErrors": 0, + "mutationRequests": 0 + } + ], + "realPortalJWT": true, + "apiMocks": false, + "cleanupCompleted": true, + "scope": "Actual compiled collector reads lab DB/native disabled GRE; no durable snapshot write, fault injection or data-plane claim", + "passwordsUnchanged": true +}