diff --git a/app/(main)/alerts/page.tsx b/app/(main)/alerts/page.tsx
index 4ae9b718..5bd992aa 100644
--- a/app/(main)/alerts/page.tsx
+++ b/app/(main)/alerts/page.tsx
@@ -10,6 +10,7 @@ import {useAlertsTargets} from "@/hooks/use-alerts-targets"
import {AlertsOutboxPanel} from "@/components/alerts-outbox-panel"
import {AlertsTelegramForm} from "@/components/alerts-telegram-form"
import {AlertsTargetsStatus} from "@/components/alerts-targets-status"
+import {AlertsTargetIssues} from "@/components/alerts-target-issues"
import { useDataSource } from "@/lib/data-source"
import { PageHeader } from "@/components/page-header"
import { FormToggle } from "@/components/form-kit"
@@ -157,6 +158,7 @@ interface AlertsGreTunnelRow {
}
interface AlertsMeta {
+ targetIssues?: AlertsResponse["meta"]["targetIssues"]
servers: string[]
greClients: string[]
probeTargets: string[]
@@ -2531,6 +2533,7 @@ function AlertsContent() {
{config.busy?
diff --git a/backend/src/services/alert-engine/collector-source-sql.test.ts b/backend/src/services/alert-engine/collector-source-sql.test.ts
index ddf5dd41..5757e52b 100644
--- a/backend/src/services/alert-engine/collector-source-sql.test.ts
+++ b/backend/src/services/alert-engine/collector-source-sql.test.ts
@@ -3,6 +3,7 @@ import { pool, closePool } from "../../db/index.js"
import { initDatabase } from "../../db/bootstrap.js"
import { buildSignalSnapshotFromCollectors } from "./signals-from-collectors.js"
import { evaluateRule } from "./evaluate-rule.js"
+import { getAlertsMeta } from "../alerts-service.js"
import type { ApiAlertRule } from "../alerts-service.js"
const database = process.env.MMAPP_OWN_SQL_DB
@@ -41,12 +42,14 @@ else {
let signals = await build()
assert.equal(signals.servers.length, 2); assert.equal(signals.servers[0].prevStatus, "online")
assert.equal(signals.trafficByServer[0].rxMbps, 0); assert.equal(signals.probes.length, 2); cases++
+ assert.deepEqual((await getAlertsMeta()).targetIssues, [])
const offlineRule = { id: "owned", name: "owned", type: "server", targets: [server().name], conditions: ["offline"], enabled: true } as ApiAlertRule
assert.ok(evaluateRule(offlineRule, signals))
await pool.query("UPDATE uptime_settings SET resources_enabled=false,ping_enabled=false WHERE id=1")
await pool.query("UPDATE traffic_settings SET enabled=false WHERE id=1")
signals = await build(); assert.deepEqual(signals.servers, []); assert.deepEqual(signals.probes, []); assert.deepEqual(signals.trafficByServer, []); cases++
+ assert((await getAlertsMeta()).targetIssues?.every(issue => issue.reason === "disabled-source"))
await pool.query("UPDATE uptime_settings SET resources_enabled=true,ping_enabled=true WHERE id=1")
await pool.query("UPDATE traffic_settings SET enabled=true WHERE id=1")
await pool.query("UPDATE servers SET enabled=false WHERE id=$1", [ids[0]])
@@ -54,6 +57,7 @@ else {
await pool.query("UPDATE servers SET enabled=true WHERE id=$1", [ids[0]])
await pool.query("UPDATE servers SET name=$1 WHERE id=$2", [server().name, ids[1]])
signals = await build(); assert.deepEqual(signals.servers, []); assert.deepEqual(signals.trafficByServer, []); cases++
+ assert.deepEqual((await getAlertsMeta()).targetIssues?.filter(issue => issue.reason === "ambiguous").map(issue => issue.kind), ["server", "traffic"])
await pool.query("UPDATE servers SET name=$1 WHERE id=$2", [server(1).name, ids[1]])
for (const broken of [null, "{", { ...snapshot("uptime_resources", []), servers: {} }, snapshot("uptime_resources", [])]) {
diff --git a/backend/src/services/alert-engine/target-issues.ts b/backend/src/services/alert-engine/target-issues.ts
new file mode 100644
index 00000000..393379b2
--- /dev/null
+++ b/backend/src/services/alert-engine/target-issues.ts
@@ -0,0 +1,33 @@
+import type { AlertTargetIssue } from "@mmapp/contracts/alerts"
+import type { CollectorSourceConfig } from "./collector-source-signals.js"
+
+/** Configuration diagnostics only. This does not claim fresh samples or Telegram delivery. */
+export function collectAlertTargetIssues(config: CollectorSourceConfig): AlertTargetIssue[] {
+ const out: AlertTargetIssue[] = []
+ const servers = new Map
()
+ for (const server of config.servers) {
+ const key = (server.name || server.host).trim().toLowerCase()
+ if (key) servers.set(key, [...(servers.get(key) ?? []), server])
+ }
+ const serverOn = (config.uptime?.resourcesEnabled ?? config.uptime?.enabled) === true || config.rest?.enabled === true
+ for (const group of servers.values()) {
+ const active = group.filter(s => s.enabled === true), target = (group[0].name || group[0].host).trim()
+ for (const [kind, sourceOn] of [["server", serverOn], ["traffic", config.traffic?.enabled === true]] as const) {
+ const reason = !active.length ? "disabled-object" : active.length > 1 ? "ambiguous" : !sourceOn ? "disabled-source" : null
+ if (reason) out.push({ kind, target, reason })
+ }
+ }
+ const probes = new Map()
+ for (const probe of config.probes) {
+ if (!probe.name.trim() || !probe.target.trim()) continue
+ const key = `${probe.name.trim()} → ${probe.target.trim()}`
+ probes.set(key, [...(probes.get(key) ?? []), probe])
+ }
+ for (const [target, group] of probes) {
+ const active = group.filter(p => p.enabled && config.servers.some(s => s.enabled === true && Number(s.id) === p.srcServerId))
+ const sourceOn = (config.uptime?.pingEnabled ?? config.uptime?.enabled) === true
+ const reason = !active.length ? "disabled-object" : active.length > 1 ? "ambiguous" : !sourceOn ? "disabled-source" : null
+ if (reason) out.push({ kind: "probe", target, reason })
+ }
+ return out
+}
diff --git a/backend/src/services/alerts-overview.test.ts b/backend/src/services/alerts-overview.test.ts
index e5e5f9d3..f78cad03 100644
--- a/backend/src/services/alerts-overview.test.ts
+++ b/backend/src/services/alerts-overview.test.ts
@@ -3,6 +3,8 @@ import assert from "node:assert/strict"
import {test} from "node:test"
import type {AlertsResponse} from "@mmapp/contracts/alerts"
import {readAlertsOverview,alertsOverviewTransaction,buildAlertsMeta} from "./alerts-overview.js"
+import {collectAlertTargetIssues} from "./alert-engine/target-issues.js"
+import type {CollectorSourceConfig} from "./alert-engine/collector-source-signals.js"
const empty:AlertsResponse={revision:alertsConfigRevision({groups:[],rules:[]}),telegram:{chatId:"",tokenConfigured:false,connected:false,messageThreadId:null},groups:[],rules:[],history:[],meta:buildAlertsMeta([],[])}
test("Alerts overview uses one context with repeatable read/read only and rejects partial snapshots",async()=>{
const context={snapshot:structuredClone(empty)},calls:string[]=[];let transactions=0
@@ -17,3 +19,21 @@ test("Alerts metadata exposes existing probe keys without synthesizing per-serve
const withoutProbes=buildAlertsMeta(servers,[]);assert.deepEqual(withoutProbes.probeTargets,[]);assert.deepEqual(withoutProbes.rttLossTargets,[]);assert.equal(withoutProbes.serversDetail[0]?.type,"")
const actual=buildAlertsMeta(servers,[{name:"probe-fixture",target:"1.1.1.1"}]);assert.deepEqual(actual.probeTargets,["probe-fixture → 1.1.1.1"]);assert.deepEqual(actual.rttLossTargets,actual.probeTargets);assert.equal(JSON.stringify(actual).includes("8.8.8.8"),false)
})
+test("Target diagnostics explain ambiguous and disabled configuration without claiming live status",()=>{
+ const config:CollectorSourceConfig={servers:[{id:1,name:"CHR",host:"one",enabled:true},{id:2,name:" chr ",host:"two",enabled:true}],probes:[],uptime:{enabled:true,resourcesEnabled:true,pingEnabled:true,intervalSec:15,probeIntervalSec:15},rest:{enabled:false,intervalSec:120},traffic:{enabled:true,intervalSec:30}}
+ assert.deepEqual(collectAlertTargetIssues(config),[{kind:"server",target:"CHR",reason:"ambiguous"},{kind:"traffic",target:"CHR",reason:"ambiguous"}])
+ const unique={...config,servers:config.servers.map((s,index)=>({...s,name:"server"+index}))}
+ assert.deepEqual(collectAlertTargetIssues(unique),[])
+ assert.deepEqual(collectAlertTargetIssues({...config,servers:[config.servers[0],{...config.servers[1],enabled:false}]}),[])
+ const disabled=collectAlertTargetIssues({...unique,servers:unique.servers.map(s=>({...s,enabled:false}))});assert.equal(disabled.length,4);assert(disabled.every(i=>i.reason==="disabled-object"))
+ const sourceOff={...unique,uptime:{...unique.uptime!,resourcesEnabled:false},traffic:{...unique.traffic!,enabled:false}}
+ assert(collectAlertTargetIssues(sourceOff).every(i=>i.reason==="disabled-source"))
+ assert.deepEqual(collectAlertTargetIssues({...sourceOff,rest:{...sourceOff.rest!,enabled:true}}).map(i=>i.kind),["traffic","traffic"])
+ const probe={id:"probe",name:"ping",target:"target",srcServerId:1,srcInterface:"",enabled:true,intervalSec:15}
+ const withProbe={...unique,probes:[probe,{...probe,id:"second"}]}
+ assert.deepEqual(collectAlertTargetIssues(withProbe),[{kind:"probe",target:"ping → target",reason:"ambiguous"}])
+ assert.deepEqual(collectAlertTargetIssues({...withProbe,probes:[probe,{...probe,id:"second",enabled:false}]}),[])
+ assert.equal(collectAlertTargetIssues({...unique,probes:[probe],uptime:{...unique.uptime!,pingEnabled:false}})[0].reason,"disabled-source")
+ const current=buildAlertsMeta(unique.servers.map(s=>({...s,site:null,country:null,type:null})),[probe],unique)
+ assert.deepEqual(current.targetIssues,[]);assert.equal("password" in current,false)
+})
diff --git a/backend/src/services/alerts-overview.ts b/backend/src/services/alerts-overview.ts
index fc154f88..23cc3344 100644
--- a/backend/src/services/alerts-overview.ts
+++ b/backend/src/services/alerts-overview.ts
@@ -1,5 +1,7 @@
import {alertsConfigRevision} from "./alerts-revision.js"
import {alertsResponseSchema,type AlertsResponse} from "@mmapp/contracts/alerts"
+import {collectAlertTargetIssues} from "./alert-engine/target-issues.js"
+import type {CollectorSourceConfig} from "./alert-engine/collector-source-signals.js"
export const alertsOverviewTransaction={isolationLevel:"repeatable read",accessMode:"read only"} as const
interface Dependencies{transaction:(work:(context:C)=>Promise,options:typeof alertsOverviewTransaction)=>Promise;telegram:(context:C)=>Promise;groups:(context:C)=>Promise;rules:(context:C)=>Promise;history:(context:C)=>Promise;meta:(context:C)=>Promise}
export async function readAlertsOverview(deps:Dependencies):Promise{
@@ -14,8 +16,8 @@ export async function readAlertsOverview(deps:Dependencies):Promiseserver.name?.trim()||server.host)
const probeTargets=probes.map(probe=>probe.name+" → "+probe.target)
- return {servers:labels,greClients:labels,probeTargets,rttLossTargets:probeTargets,trafficServers:labels,serversDetail:servers.map(server=>({name:server.name?.trim()||"",host:server.host.trim(),site:server.site?.trim()||"",country:server.country?.trim()||"",type:server.type??""}))}
+ return {servers:labels,greClients:labels,probeTargets,rttLossTargets:probeTargets,trafficServers:labels,serversDetail:servers.map(server=>({name:server.name?.trim()||"",host:server.host.trim(),site:server.site?.trim()||"",country:server.country?.trim()||"",type:server.type??""})),...(config?{targetIssues:collectAlertTargetIssues(config)}:{})}
}
diff --git a/backend/src/services/alerts-service.ts b/backend/src/services/alerts-service.ts
index c223b69d..7179232a 100644
--- a/backend/src/services/alerts-service.ts
+++ b/backend/src/services/alerts-service.ts
@@ -15,6 +15,9 @@ import {
alertTelegramSettings,
servers,
uptimeProbes,
+ uptimeSettings,
+ serversApiPingSettings,
+ trafficSettings,
} from "../db/schema.js"
export type ApiAlertGroup = {
@@ -495,6 +498,8 @@ export async function listMergedHistory(persistLimit = 40, liveCap = 25,context:
export async function getAlertsMeta(context:AlertsReadContext=db) {
const srvRows = await context
.select({
+ id: servers.id,
+ enabled: servers.enabled,
name: servers.name,
host: servers.host,
site: servers.site,
@@ -502,8 +507,12 @@ export async function getAlertsMeta(context:AlertsReadContext=db) {
type: servers.type,
})
.from(servers)
- const probes=await context.select({name:uptimeProbes.name,target:uptimeProbes.target}).from(uptimeProbes)
- return buildAlertsMeta(srvRows,probes)
+ const probes=await context.select({id:uptimeProbes.id,name:uptimeProbes.name,target:uptimeProbes.target,enabled:uptimeProbes.enabled,
+ srcServerId:uptimeProbes.srcServerId,srcInterface:uptimeProbes.srcInterface,intervalSec:uptimeProbes.intervalSec}).from(uptimeProbes)
+ const uptime=(await context.select().from(uptimeSettings).where(eq(uptimeSettings.id,1)).limit(1))[0]
+ const rest=(await context.select().from(serversApiPingSettings).where(eq(serversApiPingSettings.id,1)).limit(1))[0]
+ const traffic=(await context.select().from(trafficSettings).where(eq(trafficSettings.id,1)).limit(1))[0]
+ return buildAlertsMeta(srvRows,probes,{servers:srvRows,probes,uptime,rest,traffic})
}
export async function getAlertsOverview(){
diff --git a/components/alerts-target-issues.tsx b/components/alerts-target-issues.tsx
new file mode 100644
index 00000000..422a4d75
--- /dev/null
+++ b/components/alerts-target-issues.tsx
@@ -0,0 +1,41 @@
+import Link from "next/link"
+import { TriangleAlertIcon } from "lucide-react"
+import type { AlertTargetIssue } from "@mmapp/contracts/alerts"
+import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert"
+
+const kinds = { server: "Доступность сервера", traffic: "Трафик", probe: "Ping-проба" }
+const reasons = {
+ ambiguous: "Несколько включённых объектов имеют эту подпись. События не подтверждаются.",
+ "disabled-object": "Объект или его сервер выключен. Опрос не выполняется.",
+ "disabled-source": "Сбор данных этого типа выключен.",
+}
+export function AlertsTargetIssues({ issues }: { issues: AlertTargetIssue[] | undefined }) {
+ if (!issues?.length) return null
+ const grouped = new Map()
+ for (const issue of issues) {
+ const key = `${issue.reason}\0${issue.target}`
+ const group = grouped.get(key) ?? { target: issue.target, reason: issue.reason, kinds: [] }
+ if (!group.kinds.includes(kinds[issue.kind])) group.kinds.push(kinds[issue.kind])
+ grouped.set(key, group)
+ }
+ return
+
+ Некоторые цели оповещений требуют проверки
+
+
+ Проверить цели: {grouped.size}
+
+ {[...grouped].map(([key, group]) =>
+ {group.target} · {group.kinds.join(" / ")} — {reasons[group.reason]}
+ )}
+
+
+ {issues.some(i => i.reason === "ambiguous") && Задайте разные имена объектов, затем обновите цели существующих правил.
}
+
+ Проверить серверы
+ {issues.some(i => i.kind === "probe") && Проверить пробы}
+ {issues.some(i => i.reason === "disabled-source") && Проверить сбор данных}
+
+
+
+}
diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md
index bf5d59ab..9245e2cd 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-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;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).
@@ -696,7 +696,7 @@ flowchart LR
## 12.5.77 — основной блок IPsec (2026-10-09)
-Актуальное продолжение 2026-10-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md).
@@ -1908,3 +1908,25 @@ Readonly production PG builder подтвердил1 группу одинако
Протоколы: [SQL16/cleanup](ux-ui/acceptance/collector-sources-sql-2026-10-12.json), [source433](ux-ui/acceptance/collector-sources-source-2026-10-12.json), [compiled1008](ux-ui/acceptance/collector-sources-compiled-2026-10-12.json), [readonly production](ux-ui/acceptance/collector-sources-production-2026-10-12.json), [runtime](ux-ui/acceptance/collector-sources-runtime-2026-10-12.json), [API/UI](ux-ui/acceptance/collector-sources-deployed-2026-10-12.json).
Следующий171 — понятная диагностика неоднозначных/отключённых целей оповещений: silent suppression безопасен для engine, но пользователь должен понимать причину отсутствия события. Миграция name-based rules на stable ID, scale/multi-instance/physical WAN/внешние Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
+
+## 12.5.171 — понятные причины недоступности целей оповещений (2026-10-12)
+
+При conservative suppression170 пользователь должен понимать, почему событие не подтверждается. Добавлен чистый collectAlertTargetIssues и optional public meta.targetIssues: kind server/traffic/probe, подпись и причина ambiguous/disabled-object/disabled-source. Диагностика строится из текущих настроек внутри того же repeatable read/read only transaction, что основной overview; getters defaults не создают. Учитываются dedicated source switches, enabled REST как разрешённый availability source по конфигурации, enabled устройства/пробы, duplicate labels и fallback имени на host. Это диагностика конфигурации; она не заявляет свежесть измерений, online устройств или фактическую доставку Telegram. Поля credentials не выбираются и не публикуются. Engine правила, target representation и права не изменены.
+
+На /alerts добавлен существующий ReUI/shadcn Alert warning в base-nova/Frame композиции без изменения vendor files/theme. Строки доступности и трафика одной цели объединены; причина и дальнейшее действие читаются вместе. Длинный список раскрывается native details/summary клавиатурой, большой список изначально свёрнут; длинные подписи переносятся на телефоне. Ссылки ведут к серверам, пробам и сбору данных. При устранении причины warning исчезает после подтверждённого обновления; legacy API без optional поля не подменяется догадкой. Имена двух CHR и targets действующих правил автоматически не переписывались.
+
+| Эталон | Доработка | Проверка |
+| --- | --- | --- |
+| Существующие Alert и Frame проекта | Подпись → причина → понятный переход → обновление | [ПК1440](ux-ui/screens/alerts-target-issues-1440-2026-10-12.png), [телефон320](ux-ui/screens/alerts-target-issues-320-2026-10-12.png) |
+
+Локально прошли12 скриптов test:alerts-telegram (unit/transaction/config/queue/HTTP/JWT), application-source TypeScript, backend build и ESLint. Полный root tsc сначала захватил ignored tmp с давними test/build artifacts и выдал их ошибки; source check с исключением tmp/backend/packages прошёл, contracts/backend проверены собственной сборкой. Root tsconfig не менялся.42 unique E2E:22 readers/targets/pickers/rules/new diagnostics за44.7s;19 history/outbox/Telegram за30.6s;1 новый keyboard/long-label mobile за6.2s. Реальная отправка Telegram отсутствовала: HTTP пути подменены тестовыми receipts. Последняя проверка хронологии старым check-progress168 ожидала прежний header168; сам сохранённый historical slice имел12 dated blocks/35 существующих evidence links. Это устаревшее ожидание helper, не удаление журнала; актуальная сверка обновлена отдельно.
+
+Owned Node22/PostgreSQL18.6 profile passed19540ms:16 source SQL cases плюс проверки actual getAlertsMeta (known empty, disabled-source reasons, ambiguous server/traffic kinds),8 GRE/BGP SQL rows и actual stability;PG unavailable skips0. Временная own DB/ограниченная роль mm_accept_166_1791794042576 и test container удалены. Main fixtures/RouterOS writes/messages0. Обе production сборки прошли; source434 backend+518 frontend inputs и1012 emitted backend/contracts files совпали SHA256 (text CRLF→LF, binary unchanged). Полную UI1260/context221/backend24 regression без новой причины не повторяли.
+
+Развёртывание staged: frontend ux-targets171/version1.0.0-test.targets171 сначала принял реальный прежний API ux-sources170 без targetIssues; затем обновлён backend ux-targets171. На старом cached frontend строгий прежний DTO не знает additive поле: после обновления backend следует перезагрузить страницу для получения совместимого frontend. Менялись только image tags в existing.env; rollback tags сохранены отдельно без копирования secret env. Backend/PG healthy; frontend running/HTTP/browser подтверждён, отдельного healthcheck нет. Запущенные imageIds совпадают с проверенными образами; после cleanup3 основных running containers.
+
+2 real UI1440/320 показали настоящий CHR warning:1 сгруппированная подпись,2 affected kinds, ссылка /servers, overflow/pageerrors/API writes0. Scoped axe нового блока WCAG2A/AA violations0, full WCAG certification не заявляется. Снимки просмотрены; исходные пользовательские GRE/VXLAN images сохранены без staging/revert. Настройки/имена/пароли CHR и исходные правила не менялись.
+
+Протоколы: [SQL/cleanup](ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json), [source](ux-ui/acceptance/alert-target-issues-source-2026-10-12.json), [compiled](ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json), [interop](ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json), [runtime](ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json).
+
+Следующий172 — отдельная обнаруженная ветка: синтезированный monitoring history в alerts-service читает raw latest samples, пока не применяет enabled/freshness/current-error guards170 и требует проверки реального PG timestamp→public string на positive sample. Source finding не является уже выполненным исправлением или доказанной runtime ошибкой. Stable-ID target migration, отсутствующие цели удалённых правил, physical WAN/scale/multi-instance и реальные Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md
index b81357d6..af9cb8e6 100644
--- a/docs/ux-ui-plan.md
+++ b/docs/ux-ui-plan.md
@@ -1,12 +1,12 @@
# План реализации UX/UI по пятичасовым окнам
-Актуальное продолжение 2026-10-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-12. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
## Актуальная точка продолжения — 2026-10-12
-Актуальное продолжение 2026-10-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
Этапы0–11 завершены в локальных границах журнала. История выполненных внешних блоков и доказательства сохранены в [журнале](ux-ui-stage-12.md) и [протоколе](ux-ui-external-acceptance.md). Реальная Telegram доставка, Portal SSO, multi-instance и оставшиеся профильные сетевые ограничения открыты.
@@ -371,6 +371,6 @@ flowchart LR
## 12.5.77 — основной блок IPsec (2026-10-09)
-Актуальное продолжение 2026-10-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md).
diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md
index cfa49b46..9232b83d 100644
--- a/docs/ux-ui-progress.md
+++ b/docs/ux-ui-progress.md
@@ -1,6 +1,6 @@
# UX/UI: журнал реализации
-Актуальное продолжение 2026-10-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
@@ -38,6 +38,28 @@
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–168 и ограничения ниже. Runtime backend ux-month149/frontend ux-sessions150. |
+## 12.5.171 — понятные причины недоступности целей оповещений (2026-10-12)
+
+При conservative suppression170 пользователь должен понимать, почему событие не подтверждается. Добавлен чистый collectAlertTargetIssues и optional public meta.targetIssues: kind server/traffic/probe, подпись и причина ambiguous/disabled-object/disabled-source. Диагностика строится из текущих настроек внутри того же repeatable read/read only transaction, что основной overview; getters defaults не создают. Учитываются dedicated source switches, enabled REST как разрешённый availability source по конфигурации, enabled устройства/пробы, duplicate labels и fallback имени на host. Это диагностика конфигурации; она не заявляет свежесть измерений, online устройств или фактическую доставку Telegram. Поля credentials не выбираются и не публикуются. Engine правила, target representation и права не изменены.
+
+На /alerts добавлен существующий ReUI/shadcn Alert warning в base-nova/Frame композиции без изменения vendor files/theme. Строки доступности и трафика одной цели объединены; причина и дальнейшее действие читаются вместе. Длинный список раскрывается native details/summary клавиатурой, большой список изначально свёрнут; длинные подписи переносятся на телефоне. Ссылки ведут к серверам, пробам и сбору данных. При устранении причины warning исчезает после подтверждённого обновления; legacy API без optional поля не подменяется догадкой. Имена двух CHR и targets действующих правил автоматически не переписывались.
+
+| Эталон | Доработка | Проверка |
+| --- | --- | --- |
+| Существующие Alert и Frame проекта | Подпись → причина → понятный переход → обновление | [ПК1440](ux-ui/screens/alerts-target-issues-1440-2026-10-12.png), [телефон320](ux-ui/screens/alerts-target-issues-320-2026-10-12.png) |
+
+Локально прошли12 скриптов test:alerts-telegram (unit/transaction/config/queue/HTTP/JWT), application-source TypeScript, backend build и ESLint. Полный root tsc сначала захватил ignored tmp с давними test/build artifacts и выдал их ошибки; source check с исключением tmp/backend/packages прошёл, contracts/backend проверены собственной сборкой. Root tsconfig не менялся.42 unique E2E:22 readers/targets/pickers/rules/new diagnostics за44.7s;19 history/outbox/Telegram за30.6s;1 новый keyboard/long-label mobile за6.2s. Реальная отправка Telegram отсутствовала: HTTP пути подменены тестовыми receipts. Последняя проверка хронологии старым check-progress168 ожидала прежний header168; сам сохранённый historical slice имел12 dated blocks/35 существующих evidence links. Это устаревшее ожидание helper, не удаление журнала; актуальная сверка обновлена отдельно.
+
+Owned Node22/PostgreSQL18.6 profile passed19540ms:16 source SQL cases плюс проверки actual getAlertsMeta (known empty, disabled-source reasons, ambiguous server/traffic kinds),8 GRE/BGP SQL rows и actual stability;PG unavailable skips0. Временная own DB/ограниченная роль mm_accept_166_1791794042576 и test container удалены. Main fixtures/RouterOS writes/messages0. Обе production сборки прошли; source434 backend+518 frontend inputs и1012 emitted backend/contracts files совпали SHA256 (text CRLF→LF, binary unchanged). Полную UI1260/context221/backend24 regression без новой причины не повторяли.
+
+Развёртывание staged: frontend ux-targets171/version1.0.0-test.targets171 сначала принял реальный прежний API ux-sources170 без targetIssues; затем обновлён backend ux-targets171. На старом cached frontend строгий прежний DTO не знает additive поле: после обновления backend следует перезагрузить страницу для получения совместимого frontend. Менялись только image tags в existing.env; rollback tags сохранены отдельно без копирования secret env. Backend/PG healthy; frontend running/HTTP/browser подтверждён, отдельного healthcheck нет. Запущенные imageIds совпадают с проверенными образами; после cleanup3 основных running containers.
+
+2 real UI1440/320 показали настоящий CHR warning:1 сгруппированная подпись,2 affected kinds, ссылка /servers, overflow/pageerrors/API writes0. Scoped axe нового блока WCAG2A/AA violations0, full WCAG certification не заявляется. Снимки просмотрены; исходные пользовательские GRE/VXLAN images сохранены без staging/revert. Настройки/имена/пароли CHR и исходные правила не менялись.
+
+Протоколы: [SQL/cleanup](ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json), [source](ux-ui/acceptance/alert-target-issues-source-2026-10-12.json), [compiled](ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json), [interop](ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json), [runtime](ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json).
+
+Следующий172 — отдельная обнаруженная ветка: синтезированный monitoring history в alerts-service читает raw latest samples, пока не применяет enabled/freshness/current-error guards170 и требует проверки реального PG timestamp→public string на positive sample. Source finding не является уже выполненным исправлением или доказанной runtime ошибкой. Stable-ID target migration, отсутствующие цели удалённых правил, physical WAN/scale/multi-instance и реальные Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
+
## 12.5.170 — достоверность серверных, пробных и трафиковых сигналов (2026-10-12)
Завершён оставшийся объём169 в одном coherent backend блоке. Новый collector-source-signals отделяет чтение от чистого построения фактов. Builder читает текущие настройки и identity без seeding getters и без credentials: resourcesEnabled/pingEnabled имеют тот же fallback на legacy enabled, что scheduler; REST/traffic используют собственные enabled. Выбираются последние завершённые ok/error runs, включая NULL/error JSON, вместо only-ok history. Текущие server/traffic keys берутся только из newest run: empty/error/malformed/unknown не восстанавливают старую цель. Частичная ошибочная коллекция сохраняет известные строки других устройств. ServerID/name/host/enabled/duplicate guards169 сохранены; пустое имя может использовать host, как collector. producer sample и completion проверяются по3 effective periods, future tolerance1 period; минимумы5s resources/traffic и10s REST повторяют scheduler. Resource неизвестное значение не становится offline; Traffic требует ok=true и конечные неотрицательные RX/TX, отсутствующее/ошибка не становится0. Подтверждённый нулевой трафик остаётся0.
diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md
index 14aedbe9..15237564 100644
--- a/docs/ux-ui-remaining-acceptance.md
+++ b/docs/ux-ui-remaining-acceptance.md
@@ -1,8 +1,8 @@
# Оставшаяся внешняя приёмка — 2026-10-12
-Это актуальная матрица после 12.5.170. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии.
+Это актуальная матрица после 12.5.171. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии.
-Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-sources170`, frontend `ux-bfd158`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись.
+Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-targets171`, frontend `ux-targets171`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись.
| Раздел | Подтверждено | Осталось / условие завершения |
| --- | --- | --- |
@@ -18,7 +18,7 @@
| Recursive routes | Production PUT/change/own history restore88, disabled guards, partial/unknown/applied outcomes, live формы/контекст | Автоматический rollback/retry, durable receipts и несколько экземпляров отсутствуют; PUT не является idempotent noop. Полная произвольная legacy catalog миграция не принята |
| Diagnostics/terminal | Allowlist/native reads, Ping/trace/route/MTU/DNS, actual avg-rtt, disabled guards, JWT/live PC/mobile89; real default memory tail/log limits/API/UI133 | DNS использует backend resolver; MTU — ограниченная оценка, не гарантированный максимум. Stop ожидания не доказывает остановку RouterOS команды; arbitrary CLI и physical disconnect не приняты |
| Portal/интеграции | Локальные и isolated JWT guards; UI/API error states в границах журналов | Настоящий Portal issuer/login/отзыв прав; RIPE SDK two-IP/no-fetch passed140, native IPv6 ULA flow pipeline passed145 (IPv4 transport), public IPv6 WAN/local licensed MaxMind/S3/container/certificate jobs и Gitea delivery требуют отдельных тестовых endpoints/аккаунтов. Не отправлять сообщения и не публиковать релиз без соответствующего поручения |
-| Общая приёмка | Локальная12.3.83; UI1244/context221/compiled984 parity139; профильные build/E2E/live проверки последующих блоков | Traffic initial live mock-id gate passed141; IPv6 special ranges/cache passed142; unknown RIPE coordinates passed143; IPv6 synthetic UDP/worker/SQL passed144; native CHR ULA/IPFIX/API/UI passed145; ICMPv6/IPv6 endpoint labels passed146; HTTP DTO validation passed147; scoped flow catalog/serverId guards passed148; strict monthly calendar passed149; Sessions labels passed150; application GRE static IPv6 lifecycle151 passed; WireGuard static IPv6 lifecycle152 и disabled SQL/API gates passed; OSPF/BFD boundary/warning153 passed; OSPFv3 routes154 accepted in recorded bounds; BGP IPv6 basic155 passed; bigint ID/SQL guards156 passed; общая UI1260/context221/backend24 regression157 passed; IPv6 BFD correlation158 profile/deployed passed; native OSPFv3/BFDv6 boundary/recovery159 passed; BGP IPv6/BFD withdrawal/recovery160 passed; selected BGP/alert unknown guards161 replay/profiles/deployed passed (SQL stability skipped); private4-byte ASN162 native/API/UI passed; duplicate BGP alert keys163 replay/profiles/deployed passed; nullable selected BGP164 replay/profiles/API/UI passed; collector165 parallel/current guards/read-only PG passed; positive partial/error SQL166/full24 with PG passed (optional network SQL not repeated); GRE/BGP freshness167/SQL8 passed; other source audit168 выявил identity/disabled/freshness gaps; локальный server/traffic identity guard169 passed без SQL/deploy, source/per-probe/freshness170/ownSQL16/compiled1008/deployed passed; source diagnostics171 pending; последующие изменения проверять отдельно; scoped axe не означает полную WCAG сертификацию |
+| Общая приёмка | Локальная12.3.83; UI1244/context221/compiled984 parity139; профильные build/E2E/live проверки последующих блоков | Traffic initial live mock-id gate passed141; IPv6 special ranges/cache passed142; unknown RIPE coordinates passed143; IPv6 synthetic UDP/worker/SQL passed144; native CHR ULA/IPFIX/API/UI passed145; ICMPv6/IPv6 endpoint labels passed146; HTTP DTO validation passed147; scoped flow catalog/serverId guards passed148; strict monthly calendar passed149; Sessions labels passed150; application GRE static IPv6 lifecycle151 passed; WireGuard static IPv6 lifecycle152 и disabled SQL/API gates passed; OSPF/BFD boundary/warning153 passed; OSPFv3 routes154 accepted in recorded bounds; BGP IPv6 basic155 passed; bigint ID/SQL guards156 passed; общая UI1260/context221/backend24 regression157 passed; IPv6 BFD correlation158 profile/deployed passed; native OSPFv3/BFDv6 boundary/recovery159 passed; BGP IPv6/BFD withdrawal/recovery160 passed; selected BGP/alert unknown guards161 replay/profiles/deployed passed (SQL stability skipped); private4-byte ASN162 native/API/UI passed; duplicate BGP alert keys163 replay/profiles/deployed passed; nullable selected BGP164 replay/profiles/API/UI passed; collector165 parallel/current guards/read-only PG passed; positive partial/error SQL166/full24 with PG passed (optional network SQL not repeated); GRE/BGP freshness167/SQL8 passed; other source audit168 выявил identity/disabled/freshness gaps; локальный server/traffic identity guard169 passed без SQL/deploy, source/per-probe/freshness170/ownSQL16/compiled1008/deployed passed; source diagnostics171/42E2E/ownSQL metadata/live2 passed; synthesized monitoring history guards172 pending; последующие изменения проверять отдельно; scoped axe не означает полную WCAG сертификацию |
Доказательства и точные ограничения: [полная история этапа12](ux-ui-stage-12.md), [внешний протокол](ux-ui-external-acceptance.md), [BGP93](ux-ui/acceptance/bgp-failover-2026-10-10.json), [паспорт стенда](ux-ui-test-server.md). Невыполненные пункты не являются все блокерами данного лабораторного сценария: для выпуска необходимо явно определить требуемые конфигурации и принять их либо согласовать ограничение.
@@ -823,3 +823,25 @@ Readonly production PG builder подтвердил1 группу одинако
Протоколы: [SQL16/cleanup](ux-ui/acceptance/collector-sources-sql-2026-10-12.json), [source433](ux-ui/acceptance/collector-sources-source-2026-10-12.json), [compiled1008](ux-ui/acceptance/collector-sources-compiled-2026-10-12.json), [readonly production](ux-ui/acceptance/collector-sources-production-2026-10-12.json), [runtime](ux-ui/acceptance/collector-sources-runtime-2026-10-12.json), [API/UI](ux-ui/acceptance/collector-sources-deployed-2026-10-12.json).
Следующий171 — понятная диагностика неоднозначных/отключённых целей оповещений: silent suppression безопасен для engine, но пользователь должен понимать причину отсутствия события. Миграция name-based rules на stable ID, scale/multi-instance/physical WAN/внешние Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
+
+## 12.5.171 — понятные причины недоступности целей оповещений (2026-10-12)
+
+При conservative suppression170 пользователь должен понимать, почему событие не подтверждается. Добавлен чистый collectAlertTargetIssues и optional public meta.targetIssues: kind server/traffic/probe, подпись и причина ambiguous/disabled-object/disabled-source. Диагностика строится из текущих настроек внутри того же repeatable read/read only transaction, что основной overview; getters defaults не создают. Учитываются dedicated source switches, enabled REST как разрешённый availability source по конфигурации, enabled устройства/пробы, duplicate labels и fallback имени на host. Это диагностика конфигурации; она не заявляет свежесть измерений, online устройств или фактическую доставку Telegram. Поля credentials не выбираются и не публикуются. Engine правила, target representation и права не изменены.
+
+На /alerts добавлен существующий ReUI/shadcn Alert warning в base-nova/Frame композиции без изменения vendor files/theme. Строки доступности и трафика одной цели объединены; причина и дальнейшее действие читаются вместе. Длинный список раскрывается native details/summary клавиатурой, большой список изначально свёрнут; длинные подписи переносятся на телефоне. Ссылки ведут к серверам, пробам и сбору данных. При устранении причины warning исчезает после подтверждённого обновления; legacy API без optional поля не подменяется догадкой. Имена двух CHR и targets действующих правил автоматически не переписывались.
+
+| Эталон | Доработка | Проверка |
+| --- | --- | --- |
+| Существующие Alert и Frame проекта | Подпись → причина → понятный переход → обновление | [ПК1440](ux-ui/screens/alerts-target-issues-1440-2026-10-12.png), [телефон320](ux-ui/screens/alerts-target-issues-320-2026-10-12.png) |
+
+Локально прошли12 скриптов test:alerts-telegram (unit/transaction/config/queue/HTTP/JWT), application-source TypeScript, backend build и ESLint. Полный root tsc сначала захватил ignored tmp с давними test/build artifacts и выдал их ошибки; source check с исключением tmp/backend/packages прошёл, contracts/backend проверены собственной сборкой. Root tsconfig не менялся.42 unique E2E:22 readers/targets/pickers/rules/new diagnostics за44.7s;19 history/outbox/Telegram за30.6s;1 новый keyboard/long-label mobile за6.2s. Реальная отправка Telegram отсутствовала: HTTP пути подменены тестовыми receipts. Последняя проверка хронологии старым check-progress168 ожидала прежний header168; сам сохранённый historical slice имел12 dated blocks/35 существующих evidence links. Это устаревшее ожидание helper, не удаление журнала; актуальная сверка обновлена отдельно.
+
+Owned Node22/PostgreSQL18.6 profile passed19540ms:16 source SQL cases плюс проверки actual getAlertsMeta (known empty, disabled-source reasons, ambiguous server/traffic kinds),8 GRE/BGP SQL rows и actual stability;PG unavailable skips0. Временная own DB/ограниченная роль mm_accept_166_1791794042576 и test container удалены. Main fixtures/RouterOS writes/messages0. Обе production сборки прошли; source434 backend+518 frontend inputs и1012 emitted backend/contracts files совпали SHA256 (text CRLF→LF, binary unchanged). Полную UI1260/context221/backend24 regression без новой причины не повторяли.
+
+Развёртывание staged: frontend ux-targets171/version1.0.0-test.targets171 сначала принял реальный прежний API ux-sources170 без targetIssues; затем обновлён backend ux-targets171. На старом cached frontend строгий прежний DTO не знает additive поле: после обновления backend следует перезагрузить страницу для получения совместимого frontend. Менялись только image tags в existing.env; rollback tags сохранены отдельно без копирования secret env. Backend/PG healthy; frontend running/HTTP/browser подтверждён, отдельного healthcheck нет. Запущенные imageIds совпадают с проверенными образами; после cleanup3 основных running containers.
+
+2 real UI1440/320 показали настоящий CHR warning:1 сгруппированная подпись,2 affected kinds, ссылка /servers, overflow/pageerrors/API writes0. Scoped axe нового блока WCAG2A/AA violations0, full WCAG certification не заявляется. Снимки просмотрены; исходные пользовательские GRE/VXLAN images сохранены без staging/revert. Настройки/имена/пароли CHR и исходные правила не менялись.
+
+Протоколы: [SQL/cleanup](ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json), [source](ux-ui/acceptance/alert-target-issues-source-2026-10-12.json), [compiled](ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json), [interop](ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json), [runtime](ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json).
+
+Следующий172 — отдельная обнаруженная ветка: синтезированный monitoring history в alerts-service читает raw latest samples, пока не применяет enabled/freshness/current-error guards170 и требует проверки реального PG timestamp→public string на positive sample. Source finding не является уже выполненным исправлением или доказанной runtime ошибкой. Stable-ID target migration, отсутствующие цели удалённых правил, physical WAN/scale/multi-instance и реальные Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md
index b0af1528..afc16d97 100644
--- a/docs/ux-ui-stage-12.md
+++ b/docs/ux-ui-stage-12.md
@@ -1,6 +1,6 @@
# Этап 12: итоговая приёмка UX/UI
-Актуальное продолжение 2026-10-12: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Актуальное продолжение 2026-10-12: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
@@ -3213,3 +3213,25 @@ Readonly production PG builder подтвердил1 группу одинако
Протоколы: [SQL16/cleanup](ux-ui/acceptance/collector-sources-sql-2026-10-12.json), [source433](ux-ui/acceptance/collector-sources-source-2026-10-12.json), [compiled1008](ux-ui/acceptance/collector-sources-compiled-2026-10-12.json), [readonly production](ux-ui/acceptance/collector-sources-production-2026-10-12.json), [runtime](ux-ui/acceptance/collector-sources-runtime-2026-10-12.json), [API/UI](ux-ui/acceptance/collector-sources-deployed-2026-10-12.json).
Следующий171 — понятная диагностика неоднозначных/отключённых целей оповещений: silent suppression безопасен для engine, но пользователь должен понимать причину отсутствия события. Миграция name-based rules на stable ID, scale/multi-instance/physical WAN/внешние Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
+
+## 12.5.171 — понятные причины недоступности целей оповещений (2026-10-12)
+
+При conservative suppression170 пользователь должен понимать, почему событие не подтверждается. Добавлен чистый collectAlertTargetIssues и optional public meta.targetIssues: kind server/traffic/probe, подпись и причина ambiguous/disabled-object/disabled-source. Диагностика строится из текущих настроек внутри того же repeatable read/read only transaction, что основной overview; getters defaults не создают. Учитываются dedicated source switches, enabled REST как разрешённый availability source по конфигурации, enabled устройства/пробы, duplicate labels и fallback имени на host. Это диагностика конфигурации; она не заявляет свежесть измерений, online устройств или фактическую доставку Telegram. Поля credentials не выбираются и не публикуются. Engine правила, target representation и права не изменены.
+
+На /alerts добавлен существующий ReUI/shadcn Alert warning в base-nova/Frame композиции без изменения vendor files/theme. Строки доступности и трафика одной цели объединены; причина и дальнейшее действие читаются вместе. Длинный список раскрывается native details/summary клавиатурой, большой список изначально свёрнут; длинные подписи переносятся на телефоне. Ссылки ведут к серверам, пробам и сбору данных. При устранении причины warning исчезает после подтверждённого обновления; legacy API без optional поля не подменяется догадкой. Имена двух CHR и targets действующих правил автоматически не переписывались.
+
+| Эталон | Доработка | Проверка |
+| --- | --- | --- |
+| Существующие Alert и Frame проекта | Подпись → причина → понятный переход → обновление | [ПК1440](ux-ui/screens/alerts-target-issues-1440-2026-10-12.png), [телефон320](ux-ui/screens/alerts-target-issues-320-2026-10-12.png) |
+
+Локально прошли12 скриптов test:alerts-telegram (unit/transaction/config/queue/HTTP/JWT), application-source TypeScript, backend build и ESLint. Полный root tsc сначала захватил ignored tmp с давними test/build artifacts и выдал их ошибки; source check с исключением tmp/backend/packages прошёл, contracts/backend проверены собственной сборкой. Root tsconfig не менялся.42 unique E2E:22 readers/targets/pickers/rules/new diagnostics за44.7s;19 history/outbox/Telegram за30.6s;1 новый keyboard/long-label mobile за6.2s. Реальная отправка Telegram отсутствовала: HTTP пути подменены тестовыми receipts. Последняя проверка хронологии старым check-progress168 ожидала прежний header168; сам сохранённый historical slice имел12 dated blocks/35 существующих evidence links. Это устаревшее ожидание helper, не удаление журнала; актуальная сверка обновлена отдельно.
+
+Owned Node22/PostgreSQL18.6 profile passed19540ms:16 source SQL cases плюс проверки actual getAlertsMeta (known empty, disabled-source reasons, ambiguous server/traffic kinds),8 GRE/BGP SQL rows и actual stability;PG unavailable skips0. Временная own DB/ограниченная роль mm_accept_166_1791794042576 и test container удалены. Main fixtures/RouterOS writes/messages0. Обе production сборки прошли; source434 backend+518 frontend inputs и1012 emitted backend/contracts files совпали SHA256 (text CRLF→LF, binary unchanged). Полную UI1260/context221/backend24 regression без новой причины не повторяли.
+
+Развёртывание staged: frontend ux-targets171/version1.0.0-test.targets171 сначала принял реальный прежний API ux-sources170 без targetIssues; затем обновлён backend ux-targets171. На старом cached frontend строгий прежний DTO не знает additive поле: после обновления backend следует перезагрузить страницу для получения совместимого frontend. Менялись только image tags в existing.env; rollback tags сохранены отдельно без копирования secret env. Backend/PG healthy; frontend running/HTTP/browser подтверждён, отдельного healthcheck нет. Запущенные imageIds совпадают с проверенными образами; после cleanup3 основных running containers.
+
+2 real UI1440/320 показали настоящий CHR warning:1 сгруппированная подпись,2 affected kinds, ссылка /servers, overflow/pageerrors/API writes0. Scoped axe нового блока WCAG2A/AA violations0, full WCAG certification не заявляется. Снимки просмотрены; исходные пользовательские GRE/VXLAN images сохранены без staging/revert. Настройки/имена/пароли CHR и исходные правила не менялись.
+
+Протоколы: [SQL/cleanup](ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json), [source](ux-ui/acceptance/alert-target-issues-source-2026-10-12.json), [compiled](ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json), [interop](ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json), [runtime](ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json).
+
+Следующий172 — отдельная обнаруженная ветка: синтезированный monitoring history в alerts-service читает raw latest samples, пока не применяет enabled/freshness/current-error guards170 и требует проверки реального PG timestamp→public string на positive sample. Source finding не является уже выполненным исправлением или доказанной runtime ошибкой. Stable-ID target migration, отсутствующие цели удалённых правил, physical WAN/scale/multi-instance и реальные Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md
index 91e0a4c2..7a7fac35 100644
--- a/docs/ux-ui-test-server.md
+++ b/docs/ux-ui-test-server.md
@@ -1,6 +1,6 @@
# Тестовый сервер UX/UI — 2026-10-10
-Сервер161.104.46.222: завершён12.5.170 — source enabled/current/unknown/freshness/per-probe guards, включая169. Own PG16 source cases +GRE/BGP8/stability passed; temporary DB/role/container removed. Source433/compiled1008 parity; backend ux-sources170 healthy, frontend ux-bfd158 прежний;6 real UI/4 API reads passed, оба CHR доступны. Одноимённые server/traffic targets подавлены, имена/пароли не менялись. Следующий171 — показать неоднозначные/отключённые цели оповещений в UI и объяснить отсутствие подтверждённого сигнала;12.5 открыт.
+Сервер161.104.46.222: завершён12.5.171 — объяснение неоднозначных/отключённых целей в оповещениях, ReUI Alert без vendor changes. Backend profile/42E2E/ownPG16+metadata/compiled1012/source434+518 passed;2 live warning screens/scoped axe passed. Frontend сначала проверен с old API, затем оба ux-targets171 развёрнуты;backend/PG healthy. DB/role/container удалены. Следующий172 — исправить синтезированный журнал monitoring: raw sample readers ещё игнорируют disabled/freshness и Date needs positive SQL verification;12.5 открыт.
| Параметр | Проверенное состояние |
| --- | --- |
@@ -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-sources170 и mmapp-test/frontend:ux-bfd158; запущены |
+| Образы приложения | mmapp-test/backend:ux-targets171 и mmapp-test/frontend:ux-targets171; запущены |
Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example).
@@ -1639,3 +1639,25 @@ Readonly production PG builder подтвердил1 группу одинако
Протоколы: [SQL16/cleanup](ux-ui/acceptance/collector-sources-sql-2026-10-12.json), [source433](ux-ui/acceptance/collector-sources-source-2026-10-12.json), [compiled1008](ux-ui/acceptance/collector-sources-compiled-2026-10-12.json), [readonly production](ux-ui/acceptance/collector-sources-production-2026-10-12.json), [runtime](ux-ui/acceptance/collector-sources-runtime-2026-10-12.json), [API/UI](ux-ui/acceptance/collector-sources-deployed-2026-10-12.json).
Следующий171 — понятная диагностика неоднозначных/отключённых целей оповещений: silent suppression безопасен для engine, но пользователь должен понимать причину отсутствия события. Миграция name-based rules на stable ID, scale/multi-instance/physical WAN/внешние Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
+
+## 12.5.171 — понятные причины недоступности целей оповещений (2026-10-12)
+
+При conservative suppression170 пользователь должен понимать, почему событие не подтверждается. Добавлен чистый collectAlertTargetIssues и optional public meta.targetIssues: kind server/traffic/probe, подпись и причина ambiguous/disabled-object/disabled-source. Диагностика строится из текущих настроек внутри того же repeatable read/read only transaction, что основной overview; getters defaults не создают. Учитываются dedicated source switches, enabled REST как разрешённый availability source по конфигурации, enabled устройства/пробы, duplicate labels и fallback имени на host. Это диагностика конфигурации; она не заявляет свежесть измерений, online устройств или фактическую доставку Telegram. Поля credentials не выбираются и не публикуются. Engine правила, target representation и права не изменены.
+
+На /alerts добавлен существующий ReUI/shadcn Alert warning в base-nova/Frame композиции без изменения vendor files/theme. Строки доступности и трафика одной цели объединены; причина и дальнейшее действие читаются вместе. Длинный список раскрывается native details/summary клавиатурой, большой список изначально свёрнут; длинные подписи переносятся на телефоне. Ссылки ведут к серверам, пробам и сбору данных. При устранении причины warning исчезает после подтверждённого обновления; legacy API без optional поля не подменяется догадкой. Имена двух CHR и targets действующих правил автоматически не переписывались.
+
+| Эталон | Доработка | Проверка |
+| --- | --- | --- |
+| Существующие Alert и Frame проекта | Подпись → причина → понятный переход → обновление | [ПК1440](ux-ui/screens/alerts-target-issues-1440-2026-10-12.png), [телефон320](ux-ui/screens/alerts-target-issues-320-2026-10-12.png) |
+
+Локально прошли12 скриптов test:alerts-telegram (unit/transaction/config/queue/HTTP/JWT), application-source TypeScript, backend build и ESLint. Полный root tsc сначала захватил ignored tmp с давними test/build artifacts и выдал их ошибки; source check с исключением tmp/backend/packages прошёл, contracts/backend проверены собственной сборкой. Root tsconfig не менялся.42 unique E2E:22 readers/targets/pickers/rules/new diagnostics за44.7s;19 history/outbox/Telegram за30.6s;1 новый keyboard/long-label mobile за6.2s. Реальная отправка Telegram отсутствовала: HTTP пути подменены тестовыми receipts. Последняя проверка хронологии старым check-progress168 ожидала прежний header168; сам сохранённый historical slice имел12 dated blocks/35 существующих evidence links. Это устаревшее ожидание helper, не удаление журнала; актуальная сверка обновлена отдельно.
+
+Owned Node22/PostgreSQL18.6 profile passed19540ms:16 source SQL cases плюс проверки actual getAlertsMeta (known empty, disabled-source reasons, ambiguous server/traffic kinds),8 GRE/BGP SQL rows и actual stability;PG unavailable skips0. Временная own DB/ограниченная роль mm_accept_166_1791794042576 и test container удалены. Main fixtures/RouterOS writes/messages0. Обе production сборки прошли; source434 backend+518 frontend inputs и1012 emitted backend/contracts files совпали SHA256 (text CRLF→LF, binary unchanged). Полную UI1260/context221/backend24 regression без новой причины не повторяли.
+
+Развёртывание staged: frontend ux-targets171/version1.0.0-test.targets171 сначала принял реальный прежний API ux-sources170 без targetIssues; затем обновлён backend ux-targets171. На старом cached frontend строгий прежний DTO не знает additive поле: после обновления backend следует перезагрузить страницу для получения совместимого frontend. Менялись только image tags в existing.env; rollback tags сохранены отдельно без копирования secret env. Backend/PG healthy; frontend running/HTTP/browser подтверждён, отдельного healthcheck нет. Запущенные imageIds совпадают с проверенными образами; после cleanup3 основных running containers.
+
+2 real UI1440/320 показали настоящий CHR warning:1 сгруппированная подпись,2 affected kinds, ссылка /servers, overflow/pageerrors/API writes0. Scoped axe нового блока WCAG2A/AA violations0, full WCAG certification не заявляется. Снимки просмотрены; исходные пользовательские GRE/VXLAN images сохранены без staging/revert. Настройки/имена/пароли CHR и исходные правила не менялись.
+
+Протоколы: [SQL/cleanup](ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json), [source](ux-ui/acceptance/alert-target-issues-source-2026-10-12.json), [compiled](ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json), [interop](ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json), [runtime](ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json).
+
+Следующий172 — отдельная обнаруженная ветка: синтезированный monitoring history в alerts-service читает raw latest samples, пока не применяет enabled/freshness/current-error guards170 и требует проверки реального PG timestamp→public string на positive sample. Source finding не является уже выполненным исправлением или доказанной runtime ошибкой. Stable-ID target migration, отсутствующие цели удалённых правил, physical WAN/scale/multi-instance и реальные Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
diff --git a/docs/ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json b/docs/ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json
new file mode 100644
index 00000000..cdac2838
--- /dev/null
+++ b/docs/ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json
@@ -0,0 +1,1022 @@
+{
+ "date": "2026-10-12",
+ "block": "12.5.171",
+ "backendVersion": "1.0.0-test.targets171",
+ "normalization": "CRLF to LF",
+ "matched": [
+ "backend/dist/config.js",
+ "backend/dist/config.js.map",
+ "backend/dist/config.d.ts",
+ "backend/dist/config.d.ts.map",
+ "backend/dist/constants/ping-probe.js",
+ "backend/dist/constants/ping-probe.js.map",
+ "backend/dist/constants/ping-probe.d.ts",
+ "backend/dist/constants/ping-probe.d.ts.map",
+ "backend/dist/db/bootstrap.js",
+ "backend/dist/db/bootstrap.js.map",
+ "backend/dist/db/bootstrap.d.ts",
+ "backend/dist/db/bootstrap.d.ts.map",
+ "backend/dist/db/index.js",
+ "backend/dist/db/index.js.map",
+ "backend/dist/db/index.d.ts",
+ "backend/dist/db/index.d.ts.map",
+ "backend/dist/db/json.js",
+ "backend/dist/db/json.js.map",
+ "backend/dist/db/json.d.ts",
+ "backend/dist/db/json.d.ts.map",
+ "backend/dist/db/migrate.js",
+ "backend/dist/db/migrate.js.map",
+ "backend/dist/db/migrate.d.ts",
+ "backend/dist/db/migrate.d.ts.map",
+ "backend/dist/db/operation-lock.js",
+ "backend/dist/db/operation-lock.js.map",
+ "backend/dist/db/operation-lock.d.ts",
+ "backend/dist/db/operation-lock.d.ts.map",
+ "backend/dist/db/partitions.js",
+ "backend/dist/db/partitions.js.map",
+ "backend/dist/db/partitions.d.ts",
+ "backend/dist/db/partitions.d.ts.map",
+ "backend/dist/db/schema.js",
+ "backend/dist/db/schema.js.map",
+ "backend/dist/db/schema.d.ts",
+ "backend/dist/db/schema.d.ts.map",
+ "backend/dist/db/sql-bind.js",
+ "backend/dist/db/sql-bind.js.map",
+ "backend/dist/db/sql-bind.d.ts",
+ "backend/dist/db/sql-bind.d.ts.map",
+ "backend/dist/db/sqlite-import.js",
+ "backend/dist/db/sqlite-import.js.map",
+ "backend/dist/db/sqlite-import.d.ts",
+ "backend/dist/db/sqlite-import.d.ts.map",
+ "backend/dist/db/traffic-flags.js",
+ "backend/dist/db/traffic-flags.js.map",
+ "backend/dist/db/traffic-flags.d.ts",
+ "backend/dist/db/traffic-flags.d.ts.map",
+ "backend/dist/index.js",
+ "backend/dist/index.js.map",
+ "backend/dist/index.d.ts",
+ "backend/dist/index.d.ts.map",
+ "backend/dist/lib/permissions.js",
+ "backend/dist/lib/permissions.js.map",
+ "backend/dist/lib/permissions.d.ts",
+ "backend/dist/lib/permissions.d.ts.map",
+ "backend/dist/managed-markers.js",
+ "backend/dist/managed-markers.js.map",
+ "backend/dist/managed-markers.d.ts",
+ "backend/dist/managed-markers.d.ts.map",
+ "backend/dist/modules/events/repository/events-repository.js",
+ "backend/dist/modules/events/repository/events-repository.js.map",
+ "backend/dist/modules/events/repository/events-repository.d.ts",
+ "backend/dist/modules/events/repository/events-repository.d.ts.map",
+ "backend/dist/modules/events/service/events-service.js",
+ "backend/dist/modules/events/service/events-service.js.map",
+ "backend/dist/modules/events/service/events-service.d.ts",
+ "backend/dist/modules/events/service/events-service.d.ts.map",
+ "backend/dist/modules/servers/mapper/servers-mapper.js",
+ "backend/dist/modules/servers/mapper/servers-mapper.js.map",
+ "backend/dist/modules/servers/mapper/servers-mapper.d.ts",
+ "backend/dist/modules/servers/mapper/servers-mapper.d.ts.map",
+ "backend/dist/modules/servers/repository/servers-repository.js",
+ "backend/dist/modules/servers/repository/servers-repository.js.map",
+ "backend/dist/modules/servers/repository/servers-repository.d.ts",
+ "backend/dist/modules/servers/repository/servers-repository.d.ts.map",
+ "backend/dist/modules/servers/service/servers-service.js",
+ "backend/dist/modules/servers/service/servers-service.js.map",
+ "backend/dist/modules/servers/service/servers-service.d.ts",
+ "backend/dist/modules/servers/service/servers-service.d.ts.map",
+ "backend/dist/modules/users/iface-type.js",
+ "backend/dist/modules/users/iface-type.js.map",
+ "backend/dist/modules/users/iface-type.d.ts",
+ "backend/dist/modules/users/iface-type.d.ts.map",
+ "backend/dist/modules/users/interface-inventory.js",
+ "backend/dist/modules/users/interface-inventory.js.map",
+ "backend/dist/modules/users/interface-inventory.d.ts",
+ "backend/dist/modules/users/interface-inventory.d.ts.map",
+ "backend/dist/modules/users/peer-bind.js",
+ "backend/dist/modules/users/peer-bind.js.map",
+ "backend/dist/modules/users/peer-bind.d.ts",
+ "backend/dist/modules/users/peer-bind.d.ts.map",
+ "backend/dist/modules/users/repository/users-repository.js",
+ "backend/dist/modules/users/repository/users-repository.js.map",
+ "backend/dist/modules/users/repository/users-repository.d.ts",
+ "backend/dist/modules/users/repository/users-repository.d.ts.map",
+ "backend/dist/modules/users/service/users-service.js",
+ "backend/dist/modules/users/service/users-service.js.map",
+ "backend/dist/modules/users/service/users-service.d.ts",
+ "backend/dist/modules/users/service/users-service.d.ts.map",
+ "backend/dist/plugins/auth.js",
+ "backend/dist/plugins/auth.js.map",
+ "backend/dist/plugins/auth.d.ts",
+ "backend/dist/plugins/auth.d.ts.map",
+ "backend/dist/plugins/database-request-gate.js",
+ "backend/dist/plugins/database-request-gate.js.map",
+ "backend/dist/plugins/database-request-gate.d.ts",
+ "backend/dist/plugins/database-request-gate.d.ts.map",
+ "backend/dist/routes/alerts.js",
+ "backend/dist/routes/alerts.js.map",
+ "backend/dist/routes/alerts.d.ts",
+ "backend/dist/routes/alerts.d.ts.map",
+ "backend/dist/routes/backups.js",
+ "backend/dist/routes/backups.js.map",
+ "backend/dist/routes/backups.d.ts",
+ "backend/dist/routes/backups.d.ts.map",
+ "backend/dist/routes/bgp.js",
+ "backend/dist/routes/bgp.js.map",
+ "backend/dist/routes/bgp.d.ts",
+ "backend/dist/routes/bgp.d.ts.map",
+ "backend/dist/routes/certificates.js",
+ "backend/dist/routes/certificates.js.map",
+ "backend/dist/routes/certificates.d.ts",
+ "backend/dist/routes/certificates.d.ts.map",
+ "backend/dist/routes/containers.js",
+ "backend/dist/routes/containers.js.map",
+ "backend/dist/routes/containers.d.ts",
+ "backend/dist/routes/containers.d.ts.map",
+ "backend/dist/routes/events.js",
+ "backend/dist/routes/events.js.map",
+ "backend/dist/routes/events.d.ts",
+ "backend/dist/routes/events.d.ts.map",
+ "backend/dist/routes/evobgp-catalog.js",
+ "backend/dist/routes/evobgp-catalog.js.map",
+ "backend/dist/routes/evobgp-catalog.d.ts",
+ "backend/dist/routes/evobgp-catalog.d.ts.map",
+ "backend/dist/routes/evobgp-settings.js",
+ "backend/dist/routes/evobgp-settings.js.map",
+ "backend/dist/routes/evobgp-settings.d.ts",
+ "backend/dist/routes/evobgp-settings.d.ts.map",
+ "backend/dist/routes/evobgp.js",
+ "backend/dist/routes/evobgp.js.map",
+ "backend/dist/routes/evobgp.d.ts",
+ "backend/dist/routes/evobgp.d.ts.map",
+ "backend/dist/routes/exec.js",
+ "backend/dist/routes/exec.js.map",
+ "backend/dist/routes/exec.d.ts",
+ "backend/dist/routes/exec.d.ts.map",
+ "backend/dist/routes/filters.js",
+ "backend/dist/routes/filters.js.map",
+ "backend/dist/routes/filters.d.ts",
+ "backend/dist/routes/filters.d.ts.map",
+ "backend/dist/routes/firewall.js",
+ "backend/dist/routes/firewall.js.map",
+ "backend/dist/routes/firewall.d.ts",
+ "backend/dist/routes/firewall.d.ts.map",
+ "backend/dist/routes/geoip.js",
+ "backend/dist/routes/geoip.js.map",
+ "backend/dist/routes/geoip.d.ts",
+ "backend/dist/routes/geoip.d.ts.map",
+ "backend/dist/routes/gre.js",
+ "backend/dist/routes/gre.js.map",
+ "backend/dist/routes/gre.d.ts",
+ "backend/dist/routes/gre.d.ts.map",
+ "backend/dist/routes/internet-path.js",
+ "backend/dist/routes/internet-path.js.map",
+ "backend/dist/routes/internet-path.d.ts",
+ "backend/dist/routes/internet-path.d.ts.map",
+ "backend/dist/routes/ipsec.js",
+ "backend/dist/routes/ipsec.js.map",
+ "backend/dist/routes/ipsec.d.ts",
+ "backend/dist/routes/ipsec.d.ts.map",
+ "backend/dist/routes/network.js",
+ "backend/dist/routes/network.js.map",
+ "backend/dist/routes/network.d.ts",
+ "backend/dist/routes/network.d.ts.map",
+ "backend/dist/routes/ospf.js",
+ "backend/dist/routes/ospf.js.map",
+ "backend/dist/routes/ospf.d.ts",
+ "backend/dist/routes/ospf.d.ts.map",
+ "backend/dist/routes/ping-probes-write.js",
+ "backend/dist/routes/ping-probes-write.js.map",
+ "backend/dist/routes/ping-probes-write.d.ts",
+ "backend/dist/routes/ping-probes-write.d.ts.map",
+ "backend/dist/routes/probes.js",
+ "backend/dist/routes/probes.js.map",
+ "backend/dist/routes/probes.d.ts",
+ "backend/dist/routes/probes.d.ts.map",
+ "backend/dist/routes/recursive-routes.js",
+ "backend/dist/routes/recursive-routes.js.map",
+ "backend/dist/routes/recursive-routes.d.ts",
+ "backend/dist/routes/recursive-routes.d.ts.map",
+ "backend/dist/routes/scheduler.js",
+ "backend/dist/routes/scheduler.js.map",
+ "backend/dist/routes/scheduler.d.ts",
+ "backend/dist/routes/scheduler.d.ts.map",
+ "backend/dist/routes/servers-api-ping.js",
+ "backend/dist/routes/servers-api-ping.js.map",
+ "backend/dist/routes/servers-api-ping.d.ts",
+ "backend/dist/routes/servers-api-ping.d.ts.map",
+ "backend/dist/routes/servers.js",
+ "backend/dist/routes/servers.js.map",
+ "backend/dist/routes/servers.d.ts",
+ "backend/dist/routes/servers.d.ts.map",
+ "backend/dist/routes/sidebar-counts.js",
+ "backend/dist/routes/sidebar-counts.js.map",
+ "backend/dist/routes/sidebar-counts.d.ts",
+ "backend/dist/routes/sidebar-counts.d.ts.map",
+ "backend/dist/routes/speed-probes-write.js",
+ "backend/dist/routes/speed-probes-write.js.map",
+ "backend/dist/routes/speed-probes-write.d.ts",
+ "backend/dist/routes/speed-probes-write.d.ts.map",
+ "backend/dist/routes/speed-test.js",
+ "backend/dist/routes/speed-test.js.map",
+ "backend/dist/routes/speed-test.d.ts",
+ "backend/dist/routes/speed-test.d.ts.map",
+ "backend/dist/routes/statistics.js",
+ "backend/dist/routes/statistics.js.map",
+ "backend/dist/routes/statistics.d.ts",
+ "backend/dist/routes/statistics.d.ts.map",
+ "backend/dist/routes/system-database.js",
+ "backend/dist/routes/system-database.js.map",
+ "backend/dist/routes/system-database.d.ts",
+ "backend/dist/routes/system-database.d.ts.map",
+ "backend/dist/routes/traffic-flow-purge.js",
+ "backend/dist/routes/traffic-flow-purge.js.map",
+ "backend/dist/routes/traffic-flow-purge.d.ts",
+ "backend/dist/routes/traffic-flow-purge.d.ts.map",
+ "backend/dist/routes/traffic-flow-settings.js",
+ "backend/dist/routes/traffic-flow-settings.js.map",
+ "backend/dist/routes/traffic-flow-settings.d.ts",
+ "backend/dist/routes/traffic-flow-settings.d.ts.map",
+ "backend/dist/routes/traffic-flow.js",
+ "backend/dist/routes/traffic-flow.js.map",
+ "backend/dist/routes/traffic-flow.d.ts",
+ "backend/dist/routes/traffic-flow.d.ts.map",
+ "backend/dist/routes/traffic.js",
+ "backend/dist/routes/traffic.js.map",
+ "backend/dist/routes/traffic.d.ts",
+ "backend/dist/routes/traffic.d.ts.map",
+ "backend/dist/routes/uptime.js",
+ "backend/dist/routes/uptime.js.map",
+ "backend/dist/routes/uptime.d.ts",
+ "backend/dist/routes/uptime.d.ts.map",
+ "backend/dist/routes/users.js",
+ "backend/dist/routes/users.js.map",
+ "backend/dist/routes/users.d.ts",
+ "backend/dist/routes/users.d.ts.map",
+ "backend/dist/routes/vxlan.js",
+ "backend/dist/routes/vxlan.js.map",
+ "backend/dist/routes/vxlan.d.ts",
+ "backend/dist/routes/vxlan.d.ts.map",
+ "backend/dist/routes/wireguard.js",
+ "backend/dist/routes/wireguard.js.map",
+ "backend/dist/routes/wireguard.d.ts",
+ "backend/dist/routes/wireguard.d.ts.map",
+ "backend/dist/scripts/migrate-sqlite-to-pg.js",
+ "backend/dist/scripts/migrate-sqlite-to-pg.js.map",
+ "backend/dist/scripts/migrate-sqlite-to-pg.d.ts",
+ "backend/dist/scripts/migrate-sqlite-to-pg.d.ts.map",
+ "backend/dist/scripts/rebuild-flow-facts.js",
+ "backend/dist/scripts/rebuild-flow-facts.js.map",
+ "backend/dist/scripts/rebuild-flow-facts.d.ts",
+ "backend/dist/scripts/rebuild-flow-facts.d.ts.map",
+ "backend/dist/services/acme-cloudflare.js",
+ "backend/dist/services/acme-cloudflare.js.map",
+ "backend/dist/services/acme-cloudflare.d.ts",
+ "backend/dist/services/acme-cloudflare.d.ts.map",
+ "backend/dist/services/alert-collector-hooks.js",
+ "backend/dist/services/alert-collector-hooks.js.map",
+ "backend/dist/services/alert-collector-hooks.d.ts",
+ "backend/dist/services/alert-collector-hooks.d.ts.map",
+ "backend/dist/services/alert-engine/bgp-signals.js",
+ "backend/dist/services/alert-engine/bgp-signals.js.map",
+ "backend/dist/services/alert-engine/bgp-signals.d.ts",
+ "backend/dist/services/alert-engine/bgp-signals.d.ts.map",
+ "backend/dist/services/alert-engine/collector-source-signals.js",
+ "backend/dist/services/alert-engine/collector-source-signals.js.map",
+ "backend/dist/services/alert-engine/collector-source-signals.d.ts",
+ "backend/dist/services/alert-engine/collector-source-signals.d.ts.map",
+ "backend/dist/services/alert-engine/confirm-stability.js",
+ "backend/dist/services/alert-engine/confirm-stability.js.map",
+ "backend/dist/services/alert-engine/confirm-stability.d.ts",
+ "backend/dist/services/alert-engine/confirm-stability.d.ts.map",
+ "backend/dist/services/alert-engine/cooldown.js",
+ "backend/dist/services/alert-engine/cooldown.js.map",
+ "backend/dist/services/alert-engine/cooldown.d.ts",
+ "backend/dist/services/alert-engine/cooldown.d.ts.map",
+ "backend/dist/services/alert-engine/decision-engine.js",
+ "backend/dist/services/alert-engine/decision-engine.js.map",
+ "backend/dist/services/alert-engine/decision-engine.d.ts",
+ "backend/dist/services/alert-engine/decision-engine.d.ts.map",
+ "backend/dist/services/alert-engine/evaluate-rule.js",
+ "backend/dist/services/alert-engine/evaluate-rule.js.map",
+ "backend/dist/services/alert-engine/evaluate-rule.d.ts",
+ "backend/dist/services/alert-engine/evaluate-rule.d.ts.map",
+ "backend/dist/services/alert-engine/gre-signals.js",
+ "backend/dist/services/alert-engine/gre-signals.js.map",
+ "backend/dist/services/alert-engine/gre-signals.d.ts",
+ "backend/dist/services/alert-engine/gre-signals.d.ts.map",
+ "backend/dist/services/alert-engine/groups.js",
+ "backend/dist/services/alert-engine/groups.js.map",
+ "backend/dist/services/alert-engine/groups.d.ts",
+ "backend/dist/services/alert-engine/groups.d.ts.map",
+ "backend/dist/services/alert-engine/outbox-execution.js",
+ "backend/dist/services/alert-engine/outbox-execution.js.map",
+ "backend/dist/services/alert-engine/outbox-execution.d.ts",
+ "backend/dist/services/alert-engine/outbox-execution.d.ts.map",
+ "backend/dist/services/alert-engine/outbox.js",
+ "backend/dist/services/alert-engine/outbox.js.map",
+ "backend/dist/services/alert-engine/outbox.d.ts",
+ "backend/dist/services/alert-engine/outbox.d.ts.map",
+ "backend/dist/services/alert-engine/prev-live-store.js",
+ "backend/dist/services/alert-engine/prev-live-store.js.map",
+ "backend/dist/services/alert-engine/prev-live-store.d.ts",
+ "backend/dist/services/alert-engine/prev-live-store.d.ts.map",
+ "backend/dist/services/alert-engine/rule-matcher.js",
+ "backend/dist/services/alert-engine/rule-matcher.js.map",
+ "backend/dist/services/alert-engine/rule-matcher.d.ts",
+ "backend/dist/services/alert-engine/rule-matcher.d.ts.map",
+ "backend/dist/services/alert-engine/run-once.js",
+ "backend/dist/services/alert-engine/run-once.js.map",
+ "backend/dist/services/alert-engine/run-once.d.ts",
+ "backend/dist/services/alert-engine/run-once.d.ts.map",
+ "backend/dist/services/alert-engine/server-signal-identity.js",
+ "backend/dist/services/alert-engine/server-signal-identity.js.map",
+ "backend/dist/services/alert-engine/server-signal-identity.d.ts",
+ "backend/dist/services/alert-engine/server-signal-identity.d.ts.map",
+ "backend/dist/services/alert-engine/signal-ingestor.js",
+ "backend/dist/services/alert-engine/signal-ingestor.js.map",
+ "backend/dist/services/alert-engine/signal-ingestor.d.ts",
+ "backend/dist/services/alert-engine/signal-ingestor.d.ts.map",
+ "backend/dist/services/alert-engine/signals-from-collectors.js",
+ "backend/dist/services/alert-engine/signals-from-collectors.js.map",
+ "backend/dist/services/alert-engine/signals-from-collectors.d.ts",
+ "backend/dist/services/alert-engine/signals-from-collectors.d.ts.map",
+ "backend/dist/services/alert-engine/snapshot.js",
+ "backend/dist/services/alert-engine/snapshot.js.map",
+ "backend/dist/services/alert-engine/snapshot.d.ts",
+ "backend/dist/services/alert-engine/snapshot.d.ts.map",
+ "backend/dist/services/alert-engine/source-watermark.js",
+ "backend/dist/services/alert-engine/source-watermark.js.map",
+ "backend/dist/services/alert-engine/source-watermark.d.ts",
+ "backend/dist/services/alert-engine/source-watermark.d.ts.map",
+ "backend/dist/services/alert-engine/state-machine.js",
+ "backend/dist/services/alert-engine/state-machine.js.map",
+ "backend/dist/services/alert-engine/state-machine.d.ts",
+ "backend/dist/services/alert-engine/state-machine.d.ts.map",
+ "backend/dist/services/alert-engine/telegram-emoji.js",
+ "backend/dist/services/alert-engine/telegram-emoji.js.map",
+ "backend/dist/services/alert-engine/telegram-emoji.d.ts",
+ "backend/dist/services/alert-engine/telegram-emoji.d.ts.map",
+ "backend/dist/services/alert-engine/types.js",
+ "backend/dist/services/alert-engine/types.js.map",
+ "backend/dist/services/alert-engine/types.d.ts",
+ "backend/dist/services/alert-engine/types.d.ts.map",
+ "backend/dist/services/alerts-config-execution.js",
+ "backend/dist/services/alerts-config-execution.js.map",
+ "backend/dist/services/alerts-config-execution.d.ts",
+ "backend/dist/services/alerts-config-execution.d.ts.map",
+ "backend/dist/services/alerts-outbox-overview.js",
+ "backend/dist/services/alerts-outbox-overview.js.map",
+ "backend/dist/services/alerts-outbox-overview.d.ts",
+ "backend/dist/services/alerts-outbox-overview.d.ts.map",
+ "backend/dist/services/alerts-outbox-retry.js",
+ "backend/dist/services/alerts-outbox-retry.js.map",
+ "backend/dist/services/alerts-outbox-retry.d.ts",
+ "backend/dist/services/alerts-outbox-retry.d.ts.map",
+ "backend/dist/services/alerts-overview.js",
+ "backend/dist/services/alerts-overview.js.map",
+ "backend/dist/services/alerts-overview.d.ts",
+ "backend/dist/services/alerts-overview.d.ts.map",
+ "backend/dist/services/alerts-revision.js",
+ "backend/dist/services/alerts-revision.js.map",
+ "backend/dist/services/alerts-revision.d.ts",
+ "backend/dist/services/alerts-revision.d.ts.map",
+ "backend/dist/services/alerts-service.js",
+ "backend/dist/services/alerts-service.js.map",
+ "backend/dist/services/alerts-service.d.ts",
+ "backend/dist/services/alerts-service.d.ts.map",
+ "backend/dist/services/alerts-telegram-delivery.js",
+ "backend/dist/services/alerts-telegram-delivery.js.map",
+ "backend/dist/services/alerts-telegram-delivery.d.ts",
+ "backend/dist/services/alerts-telegram-delivery.d.ts.map",
+ "backend/dist/services/alerts-telegram-send.js",
+ "backend/dist/services/alerts-telegram-send.js.map",
+ "backend/dist/services/alerts-telegram-send.d.ts",
+ "backend/dist/services/alerts-telegram-send.d.ts.map",
+ "backend/dist/services/alerts-telegram-settings.js",
+ "backend/dist/services/alerts-telegram-settings.js.map",
+ "backend/dist/services/alerts-telegram-settings.d.ts",
+ "backend/dist/services/alerts-telegram-settings.d.ts.map",
+ "backend/dist/services/backup-deletion.js",
+ "backend/dist/services/backup-deletion.js.map",
+ "backend/dist/services/backup-deletion.d.ts",
+ "backend/dist/services/backup-deletion.d.ts.map",
+ "backend/dist/services/backup-dto.js",
+ "backend/dist/services/backup-dto.js.map",
+ "backend/dist/services/backup-dto.d.ts",
+ "backend/dist/services/backup-dto.d.ts.map",
+ "backend/dist/services/backup-job-execution.js",
+ "backend/dist/services/backup-job-execution.js.map",
+ "backend/dist/services/backup-job-execution.d.ts",
+ "backend/dist/services/backup-job-execution.d.ts.map",
+ "backend/dist/services/backup-prune.js",
+ "backend/dist/services/backup-prune.js.map",
+ "backend/dist/services/backup-prune.d.ts",
+ "backend/dist/services/backup-prune.d.ts.map",
+ "backend/dist/services/backup-restore.js",
+ "backend/dist/services/backup-restore.js.map",
+ "backend/dist/services/backup-restore.d.ts",
+ "backend/dist/services/backup-restore.d.ts.map",
+ "backend/dist/services/backup-scheduler-collector.js",
+ "backend/dist/services/backup-scheduler-collector.js.map",
+ "backend/dist/services/backup-scheduler-collector.d.ts",
+ "backend/dist/services/backup-scheduler-collector.d.ts.map",
+ "backend/dist/services/backup-scheduler-run.js",
+ "backend/dist/services/backup-scheduler-run.js.map",
+ "backend/dist/services/backup-scheduler-run.d.ts",
+ "backend/dist/services/backup-scheduler-run.d.ts.map",
+ "backend/dist/services/backup-service.js",
+ "backend/dist/services/backup-service.js.map",
+ "backend/dist/services/backup-service.d.ts",
+ "backend/dist/services/backup-service.d.ts.map",
+ "backend/dist/services/backup-storage-update.js",
+ "backend/dist/services/backup-storage-update.js.map",
+ "backend/dist/services/backup-storage-update.d.ts",
+ "backend/dist/services/backup-storage-update.d.ts.map",
+ "backend/dist/services/bandwidth-test-rates.js",
+ "backend/dist/services/bandwidth-test-rates.js.map",
+ "backend/dist/services/bandwidth-test-rates.d.ts",
+ "backend/dist/services/bandwidth-test-rates.d.ts.map",
+ "backend/dist/services/bandwidth-test-status.js",
+ "backend/dist/services/bandwidth-test-status.js.map",
+ "backend/dist/services/bandwidth-test-status.d.ts",
+ "backend/dist/services/bandwidth-test-status.d.ts.map",
+ "backend/dist/services/bgp-catalog-poll.js",
+ "backend/dist/services/bgp-catalog-poll.js.map",
+ "backend/dist/services/bgp-catalog-poll.d.ts",
+ "backend/dist/services/bgp-catalog-poll.d.ts.map",
+ "backend/dist/services/bgp-parse-sessions.js",
+ "backend/dist/services/bgp-parse-sessions.js.map",
+ "backend/dist/services/bgp-parse-sessions.d.ts",
+ "backend/dist/services/bgp-parse-sessions.d.ts.map",
+ "backend/dist/services/bgp-peers-live.js",
+ "backend/dist/services/bgp-peers-live.js.map",
+ "backend/dist/services/bgp-peers-live.d.ts",
+ "backend/dist/services/bgp-peers-live.d.ts.map",
+ "backend/dist/services/btest-node-locks.js",
+ "backend/dist/services/btest-node-locks.js.map",
+ "backend/dist/services/btest-node-locks.d.ts",
+ "backend/dist/services/btest-node-locks.d.ts.map",
+ "backend/dist/services/certificate-issue-dto.js",
+ "backend/dist/services/certificate-issue-dto.js.map",
+ "backend/dist/services/certificate-issue-dto.d.ts",
+ "backend/dist/services/certificate-issue-dto.d.ts.map",
+ "backend/dist/services/certificate-issue-execution.js",
+ "backend/dist/services/certificate-issue-execution.js.map",
+ "backend/dist/services/certificate-issue-execution.d.ts",
+ "backend/dist/services/certificate-issue-execution.d.ts.map",
+ "backend/dist/services/certificate-issue-request.js",
+ "backend/dist/services/certificate-issue-request.js.map",
+ "backend/dist/services/certificate-issue-request.d.ts",
+ "backend/dist/services/certificate-issue-request.d.ts.map",
+ "backend/dist/services/certificate-issue-runner.js",
+ "backend/dist/services/certificate-issue-runner.js.map",
+ "backend/dist/services/certificate-issue-runner.d.ts",
+ "backend/dist/services/certificate-issue-runner.d.ts.map",
+ "backend/dist/services/certificate-parse.js",
+ "backend/dist/services/certificate-parse.js.map",
+ "backend/dist/services/certificate-parse.d.ts",
+ "backend/dist/services/certificate-parse.d.ts.map",
+ "backend/dist/services/certificate-renew-collector.js",
+ "backend/dist/services/certificate-renew-collector.js.map",
+ "backend/dist/services/certificate-renew-collector.d.ts",
+ "backend/dist/services/certificate-renew-collector.d.ts.map",
+ "backend/dist/services/certificates-service.js",
+ "backend/dist/services/certificates-service.js.map",
+ "backend/dist/services/certificates-service.d.ts",
+ "backend/dist/services/certificates-service.d.ts.map",
+ "backend/dist/services/certificates-state.js",
+ "backend/dist/services/certificates-state.js.map",
+ "backend/dist/services/certificates-state.d.ts",
+ "backend/dist/services/certificates-state.d.ts.map",
+ "backend/dist/services/complete-count.js",
+ "backend/dist/services/complete-count.js.map",
+ "backend/dist/services/complete-count.d.ts",
+ "backend/dist/services/complete-count.d.ts.map",
+ "backend/dist/services/config-apply-plan.js",
+ "backend/dist/services/config-apply-plan.js.map",
+ "backend/dist/services/config-apply-plan.d.ts",
+ "backend/dist/services/config-apply-plan.d.ts.map",
+ "backend/dist/services/config-revisions.js",
+ "backend/dist/services/config-revisions.js.map",
+ "backend/dist/services/config-revisions.d.ts",
+ "backend/dist/services/config-revisions.d.ts.map",
+ "backend/dist/services/containers-live.js",
+ "backend/dist/services/containers-live.js.map",
+ "backend/dist/services/containers-live.d.ts",
+ "backend/dist/services/containers-live.d.ts.map",
+ "backend/dist/services/containers-state.js",
+ "backend/dist/services/containers-state.js.map",
+ "backend/dist/services/containers-state.d.ts",
+ "backend/dist/services/containers-state.d.ts.map",
+ "backend/dist/services/database-background-work.js",
+ "backend/dist/services/database-background-work.js.map",
+ "backend/dist/services/database-background-work.d.ts",
+ "backend/dist/services/database-background-work.d.ts.map",
+ "backend/dist/services/database-request-gate.js",
+ "backend/dist/services/database-request-gate.js.map",
+ "backend/dist/services/database-request-gate.d.ts",
+ "backend/dist/services/database-request-gate.d.ts.map",
+ "backend/dist/services/entity-snapshots.js",
+ "backend/dist/services/entity-snapshots.js.map",
+ "backend/dist/services/entity-snapshots.d.ts",
+ "backend/dist/services/entity-snapshots.d.ts.map",
+ "backend/dist/services/evobgp-catalog.js",
+ "backend/dist/services/evobgp-catalog.js.map",
+ "backend/dist/services/evobgp-catalog.d.ts",
+ "backend/dist/services/evobgp-catalog.d.ts.map",
+ "backend/dist/services/firewall-live.js",
+ "backend/dist/services/firewall-live.js.map",
+ "backend/dist/services/firewall-live.d.ts",
+ "backend/dist/services/firewall-live.d.ts.map",
+ "backend/dist/services/firewall-poll.js",
+ "backend/dist/services/firewall-poll.js.map",
+ "backend/dist/services/firewall-poll.d.ts",
+ "backend/dist/services/firewall-poll.d.ts.map",
+ "backend/dist/services/geoip-settings.js",
+ "backend/dist/services/geoip-settings.js.map",
+ "backend/dist/services/geoip-settings.d.ts",
+ "backend/dist/services/geoip-settings.d.ts.map",
+ "backend/dist/services/geoip-update-collector.js",
+ "backend/dist/services/geoip-update-collector.js.map",
+ "backend/dist/services/geoip-update-collector.d.ts",
+ "backend/dist/services/geoip-update-collector.d.ts.map",
+ "backend/dist/services/gre-bgp-snapshot-collector.js",
+ "backend/dist/services/gre-bgp-snapshot-collector.js.map",
+ "backend/dist/services/gre-bgp-snapshot-collector.d.ts",
+ "backend/dist/services/gre-bgp-snapshot-collector.d.ts.map",
+ "backend/dist/services/gre-bgp-snapshot-history.js",
+ "backend/dist/services/gre-bgp-snapshot-history.js.map",
+ "backend/dist/services/gre-bgp-snapshot-history.d.ts",
+ "backend/dist/services/gre-bgp-snapshot-history.d.ts.map",
+ "backend/dist/services/gre-bgp-timing.js",
+ "backend/dist/services/gre-bgp-timing.js.map",
+ "backend/dist/services/gre-bgp-timing.d.ts",
+ "backend/dist/services/gre-bgp-timing.d.ts.map",
+ "backend/dist/services/gre-catalog-poll.js",
+ "backend/dist/services/gre-catalog-poll.js.map",
+ "backend/dist/services/gre-catalog-poll.d.ts",
+ "backend/dist/services/gre-catalog-poll.d.ts.map",
+ "backend/dist/services/gre-comment.js",
+ "backend/dist/services/gre-comment.js.map",
+ "backend/dist/services/gre-comment.d.ts",
+ "backend/dist/services/gre-comment.d.ts.map",
+ "backend/dist/services/gre-live.js",
+ "backend/dist/services/gre-live.js.map",
+ "backend/dist/services/gre-live.d.ts",
+ "backend/dist/services/gre-live.d.ts.map",
+ "backend/dist/services/gre-tunnels-live.js",
+ "backend/dist/services/gre-tunnels-live.js.map",
+ "backend/dist/services/gre-tunnels-live.d.ts",
+ "backend/dist/services/gre-tunnels-live.d.ts.map",
+ "backend/dist/services/internet-path-collector.js",
+ "backend/dist/services/internet-path-collector.js.map",
+ "backend/dist/services/internet-path-collector.d.ts",
+ "backend/dist/services/internet-path-collector.d.ts.map",
+ "backend/dist/services/internet-path-snapshot.js",
+ "backend/dist/services/internet-path-snapshot.js.map",
+ "backend/dist/services/internet-path-snapshot.d.ts",
+ "backend/dist/services/internet-path-snapshot.d.ts.map",
+ "backend/dist/services/ipsec-ca.js",
+ "backend/dist/services/ipsec-ca.js.map",
+ "backend/dist/services/ipsec-ca.d.ts",
+ "backend/dist/services/ipsec-ca.d.ts.map",
+ "backend/dist/services/ipsec-certificate-dn.js",
+ "backend/dist/services/ipsec-certificate-dn.js.map",
+ "backend/dist/services/ipsec-certificate-dn.d.ts",
+ "backend/dist/services/ipsec-certificate-dn.d.ts.map",
+ "backend/dist/services/ipsec-cleanup.js",
+ "backend/dist/services/ipsec-cleanup.js.map",
+ "backend/dist/services/ipsec-cleanup.d.ts",
+ "backend/dist/services/ipsec-cleanup.d.ts.map",
+ "backend/dist/services/ipsec-config.js",
+ "backend/dist/services/ipsec-config.js.map",
+ "backend/dist/services/ipsec-config.d.ts",
+ "backend/dist/services/ipsec-config.d.ts.map",
+ "backend/dist/services/ipsec-live.js",
+ "backend/dist/services/ipsec-live.js.map",
+ "backend/dist/services/ipsec-live.d.ts",
+ "backend/dist/services/ipsec-live.d.ts.map",
+ "backend/dist/services/ipsec-operation.js",
+ "backend/dist/services/ipsec-operation.js.map",
+ "backend/dist/services/ipsec-operation.d.ts",
+ "backend/dist/services/ipsec-operation.d.ts.map",
+ "backend/dist/services/ipsec-ros.js",
+ "backend/dist/services/ipsec-ros.js.map",
+ "backend/dist/services/ipsec-ros.d.ts",
+ "backend/dist/services/ipsec-ros.d.ts.map",
+ "backend/dist/services/mikrotik.js",
+ "backend/dist/services/mikrotik.js.map",
+ "backend/dist/services/mikrotik.d.ts",
+ "backend/dist/services/mikrotik.d.ts.map",
+ "backend/dist/services/monitoring-server-catalog.js",
+ "backend/dist/services/monitoring-server-catalog.js.map",
+ "backend/dist/services/monitoring-server-catalog.d.ts",
+ "backend/dist/services/monitoring-server-catalog.d.ts.map",
+ "backend/dist/services/ospf-catalog-poll.js",
+ "backend/dist/services/ospf-catalog-poll.js.map",
+ "backend/dist/services/ospf-catalog-poll.d.ts",
+ "backend/dist/services/ospf-catalog-poll.d.ts.map",
+ "backend/dist/services/ospf-effective-disabled.js",
+ "backend/dist/services/ospf-effective-disabled.js.map",
+ "backend/dist/services/ospf-effective-disabled.d.ts",
+ "backend/dist/services/ospf-effective-disabled.d.ts.map",
+ "backend/dist/services/ospf-observed-values.js",
+ "backend/dist/services/ospf-observed-values.js.map",
+ "backend/dist/services/ospf-observed-values.d.ts",
+ "backend/dist/services/ospf-observed-values.d.ts.map",
+ "backend/dist/services/ospf-optimizer-identity.js",
+ "backend/dist/services/ospf-optimizer-identity.js.map",
+ "backend/dist/services/ospf-optimizer-identity.d.ts",
+ "backend/dist/services/ospf-optimizer-identity.d.ts.map",
+ "backend/dist/services/ospf-optimizer-metrics.js",
+ "backend/dist/services/ospf-optimizer-metrics.js.map",
+ "backend/dist/services/ospf-optimizer-metrics.d.ts",
+ "backend/dist/services/ospf-optimizer-metrics.d.ts.map",
+ "backend/dist/services/ospf-optimizer-plan.js",
+ "backend/dist/services/ospf-optimizer-plan.js.map",
+ "backend/dist/services/ospf-optimizer-plan.d.ts",
+ "backend/dist/services/ospf-optimizer-plan.d.ts.map",
+ "backend/dist/services/ospf-route-parse.js",
+ "backend/dist/services/ospf-route-parse.js.map",
+ "backend/dist/services/ospf-route-parse.d.ts",
+ "backend/dist/services/ospf-route-parse.d.ts.map",
+ "backend/dist/services/ping-probe-replacement.js",
+ "backend/dist/services/ping-probe-replacement.js.map",
+ "backend/dist/services/ping-probe-replacement.d.ts",
+ "backend/dist/services/ping-probe-replacement.d.ts.map",
+ "backend/dist/services/poller.js",
+ "backend/dist/services/poller.js.map",
+ "backend/dist/services/poller.d.ts",
+ "backend/dist/services/poller.d.ts.map",
+ "backend/dist/services/recursive-apply.js",
+ "backend/dist/services/recursive-apply.js.map",
+ "backend/dist/services/recursive-apply.d.ts",
+ "backend/dist/services/recursive-apply.d.ts.map",
+ "backend/dist/services/recursive-route-catalog.js",
+ "backend/dist/services/recursive-route-catalog.js.map",
+ "backend/dist/services/recursive-route-catalog.d.ts",
+ "backend/dist/services/recursive-route-catalog.d.ts.map",
+ "backend/dist/services/recursive-route-validation.js",
+ "backend/dist/services/recursive-route-validation.js.map",
+ "backend/dist/services/recursive-route-validation.d.ts",
+ "backend/dist/services/recursive-route-validation.d.ts.map",
+ "backend/dist/services/ros-metric-parse.js",
+ "backend/dist/services/ros-metric-parse.js.map",
+ "backend/dist/services/ros-metric-parse.d.ts",
+ "backend/dist/services/ros-metric-parse.d.ts.map",
+ "backend/dist/services/ros-ops.js",
+ "backend/dist/services/ros-ops.js.map",
+ "backend/dist/services/ros-ops.d.ts",
+ "backend/dist/services/ros-ops.d.ts.map",
+ "backend/dist/services/s3-backup-client.js",
+ "backend/dist/services/s3-backup-client.js.map",
+ "backend/dist/services/s3-backup-client.d.ts",
+ "backend/dist/services/s3-backup-client.d.ts.map",
+ "backend/dist/services/scheduler-recorded-run.js",
+ "backend/dist/services/scheduler-recorded-run.js.map",
+ "backend/dist/services/scheduler-recorded-run.d.ts",
+ "backend/dist/services/scheduler-recorded-run.d.ts.map",
+ "backend/dist/services/scheduler-running.js",
+ "backend/dist/services/scheduler-running.js.map",
+ "backend/dist/services/scheduler-running.d.ts",
+ "backend/dist/services/scheduler-running.d.ts.map",
+ "backend/dist/services/scheduler.js",
+ "backend/dist/services/scheduler.js.map",
+ "backend/dist/services/scheduler.d.ts",
+ "backend/dist/services/scheduler.d.ts.map",
+ "backend/dist/services/serial-operation.js",
+ "backend/dist/services/serial-operation.js.map",
+ "backend/dist/services/serial-operation.d.ts",
+ "backend/dist/services/serial-operation.d.ts.map",
+ "backend/dist/services/servers-rest-ping-collector.js",
+ "backend/dist/services/servers-rest-ping-collector.js.map",
+ "backend/dist/services/servers-rest-ping-collector.d.ts",
+ "backend/dist/services/servers-rest-ping-collector.d.ts.map",
+ "backend/dist/services/speed-history-dto.js",
+ "backend/dist/services/speed-history-dto.js.map",
+ "backend/dist/services/speed-history-dto.d.ts",
+ "backend/dist/services/speed-history-dto.d.ts.map",
+ "backend/dist/services/speed-probe-dto.js",
+ "backend/dist/services/speed-probe-dto.js.map",
+ "backend/dist/services/speed-probe-dto.d.ts",
+ "backend/dist/services/speed-probe-dto.d.ts.map",
+ "backend/dist/services/speed-probe-replacement.js",
+ "backend/dist/services/speed-probe-replacement.js.map",
+ "backend/dist/services/speed-probe-replacement.d.ts",
+ "backend/dist/services/speed-probe-replacement.d.ts.map",
+ "backend/dist/services/speed-run-error-message.js",
+ "backend/dist/services/speed-run-error-message.js.map",
+ "backend/dist/services/speed-run-error-message.d.ts",
+ "backend/dist/services/speed-run-error-message.d.ts.map",
+ "backend/dist/services/speed-run-persistence.js",
+ "backend/dist/services/speed-run-persistence.js.map",
+ "backend/dist/services/speed-run-persistence.d.ts",
+ "backend/dist/services/speed-run-persistence.d.ts.map",
+ "backend/dist/services/statistics-aggregate.js",
+ "backend/dist/services/statistics-aggregate.js.map",
+ "backend/dist/services/statistics-aggregate.d.ts",
+ "backend/dist/services/statistics-aggregate.d.ts.map",
+ "backend/dist/services/system-database-backup.js",
+ "backend/dist/services/system-database-backup.js.map",
+ "backend/dist/services/system-database-backup.d.ts",
+ "backend/dist/services/system-database-backup.d.ts.map",
+ "backend/dist/services/system-database-cache.js",
+ "backend/dist/services/system-database-cache.js.map",
+ "backend/dist/services/system-database-cache.d.ts",
+ "backend/dist/services/system-database-cache.d.ts.map",
+ "backend/dist/services/system-database-operation.js",
+ "backend/dist/services/system-database-operation.js.map",
+ "backend/dist/services/system-database-operation.d.ts",
+ "backend/dist/services/system-database-operation.d.ts.map",
+ "backend/dist/services/system-database-partition-restore.js",
+ "backend/dist/services/system-database-partition-restore.js.map",
+ "backend/dist/services/system-database-partition-restore.d.ts",
+ "backend/dist/services/system-database-partition-restore.d.ts.map",
+ "backend/dist/services/system-database-restore-execution.js",
+ "backend/dist/services/system-database-restore-execution.js.map",
+ "backend/dist/services/system-database-restore-execution.d.ts",
+ "backend/dist/services/system-database-restore-execution.d.ts.map",
+ "backend/dist/services/traffic-collector.js",
+ "backend/dist/services/traffic-collector.js.map",
+ "backend/dist/services/traffic-collector.d.ts",
+ "backend/dist/services/traffic-collector.d.ts.map",
+ "backend/dist/services/traffic-flow-analytics.js",
+ "backend/dist/services/traffic-flow-analytics.js.map",
+ "backend/dist/services/traffic-flow-analytics.d.ts",
+ "backend/dist/services/traffic-flow-analytics.d.ts.map",
+ "backend/dist/services/traffic-flow-apps.js",
+ "backend/dist/services/traffic-flow-apps.js.map",
+ "backend/dist/services/traffic-flow-apps.d.ts",
+ "backend/dist/services/traffic-flow-apps.d.ts.map",
+ "backend/dist/services/traffic-flow-brands.js",
+ "backend/dist/services/traffic-flow-brands.js.map",
+ "backend/dist/services/traffic-flow-brands.d.ts",
+ "backend/dist/services/traffic-flow-brands.d.ts.map",
+ "backend/dist/services/traffic-flow-classify.js",
+ "backend/dist/services/traffic-flow-classify.js.map",
+ "backend/dist/services/traffic-flow-classify.d.ts",
+ "backend/dist/services/traffic-flow-classify.d.ts.map",
+ "backend/dist/services/traffic-flow-collector-ipc.js",
+ "backend/dist/services/traffic-flow-collector-ipc.js.map",
+ "backend/dist/services/traffic-flow-collector-ipc.d.ts",
+ "backend/dist/services/traffic-flow-collector-ipc.d.ts.map",
+ "backend/dist/services/traffic-flow-collector-worker.js",
+ "backend/dist/services/traffic-flow-collector-worker.js.map",
+ "backend/dist/services/traffic-flow-collector-worker.d.ts",
+ "backend/dist/services/traffic-flow-collector-worker.d.ts.map",
+ "backend/dist/services/traffic-flow-dedup.js",
+ "backend/dist/services/traffic-flow-dedup.js.map",
+ "backend/dist/services/traffic-flow-dedup.d.ts",
+ "backend/dist/services/traffic-flow-dedup.d.ts.map",
+ "backend/dist/services/traffic-flow-dest.js",
+ "backend/dist/services/traffic-flow-dest.js.map",
+ "backend/dist/services/traffic-flow-dest.d.ts",
+ "backend/dist/services/traffic-flow-dest.d.ts.map",
+ "backend/dist/services/traffic-flow-engine.js",
+ "backend/dist/services/traffic-flow-engine.js.map",
+ "backend/dist/services/traffic-flow-engine.d.ts",
+ "backend/dist/services/traffic-flow-engine.d.ts.map",
+ "backend/dist/services/traffic-flow-facts-filter.js",
+ "backend/dist/services/traffic-flow-facts-filter.js.map",
+ "backend/dist/services/traffic-flow-facts-filter.d.ts",
+ "backend/dist/services/traffic-flow-facts-filter.d.ts.map",
+ "backend/dist/services/traffic-flow-facts-rebuild.js",
+ "backend/dist/services/traffic-flow-facts-rebuild.js.map",
+ "backend/dist/services/traffic-flow-facts-rebuild.d.ts",
+ "backend/dist/services/traffic-flow-facts-rebuild.d.ts.map",
+ "backend/dist/services/traffic-flow-facts.js",
+ "backend/dist/services/traffic-flow-facts.js.map",
+ "backend/dist/services/traffic-flow-facts.d.ts",
+ "backend/dist/services/traffic-flow-facts.d.ts.map",
+ "backend/dist/services/traffic-flow-geoip.js",
+ "backend/dist/services/traffic-flow-geoip.js.map",
+ "backend/dist/services/traffic-flow-geoip.d.ts",
+ "backend/dist/services/traffic-flow-geoip.d.ts.map",
+ "backend/dist/services/traffic-flow-host-file-builders.js",
+ "backend/dist/services/traffic-flow-host-file-builders.js.map",
+ "backend/dist/services/traffic-flow-host-file-builders.d.ts",
+ "backend/dist/services/traffic-flow-host-file-builders.d.ts.map",
+ "backend/dist/services/traffic-flow-host-files.js",
+ "backend/dist/services/traffic-flow-host-files.js.map",
+ "backend/dist/services/traffic-flow-host-files.d.ts",
+ "backend/dist/services/traffic-flow-host-files.d.ts.map",
+ "backend/dist/services/traffic-flow-ifaces.js",
+ "backend/dist/services/traffic-flow-ifaces.js.map",
+ "backend/dist/services/traffic-flow-ifaces.d.ts",
+ "backend/dist/services/traffic-flow-ifaces.d.ts.map",
+ "backend/dist/services/traffic-flow-ifindex.js",
+ "backend/dist/services/traffic-flow-ifindex.js.map",
+ "backend/dist/services/traffic-flow-ifindex.d.ts",
+ "backend/dist/services/traffic-flow-ifindex.d.ts.map",
+ "backend/dist/services/traffic-flow-ingest.js",
+ "backend/dist/services/traffic-flow-ingest.js.map",
+ "backend/dist/services/traffic-flow-ingest.d.ts",
+ "backend/dist/services/traffic-flow-ingest.d.ts.map",
+ "backend/dist/services/traffic-flow-ip.js",
+ "backend/dist/services/traffic-flow-ip.js.map",
+ "backend/dist/services/traffic-flow-ip.d.ts",
+ "backend/dist/services/traffic-flow-ip.d.ts.map",
+ "backend/dist/services/traffic-flow-key-execution.js",
+ "backend/dist/services/traffic-flow-key-execution.js.map",
+ "backend/dist/services/traffic-flow-key-execution.d.ts",
+ "backend/dist/services/traffic-flow-key-execution.d.ts.map",
+ "backend/dist/services/traffic-flow-map-exporter.js",
+ "backend/dist/services/traffic-flow-map-exporter.js.map",
+ "backend/dist/services/traffic-flow-map-exporter.d.ts",
+ "backend/dist/services/traffic-flow-map-exporter.d.ts.map",
+ "backend/dist/services/traffic-flow-map-hops.js",
+ "backend/dist/services/traffic-flow-map-hops.js.map",
+ "backend/dist/services/traffic-flow-map-hops.d.ts",
+ "backend/dist/services/traffic-flow-map-hops.d.ts.map",
+ "backend/dist/services/traffic-flow-overlay.js",
+ "backend/dist/services/traffic-flow-overlay.js.map",
+ "backend/dist/services/traffic-flow-overlay.d.ts",
+ "backend/dist/services/traffic-flow-overlay.d.ts.map",
+ "backend/dist/services/traffic-flow-parse.js",
+ "backend/dist/services/traffic-flow-parse.js.map",
+ "backend/dist/services/traffic-flow-parse.d.ts",
+ "backend/dist/services/traffic-flow-parse.d.ts.map",
+ "backend/dist/services/traffic-flow-planes.js",
+ "backend/dist/services/traffic-flow-planes.js.map",
+ "backend/dist/services/traffic-flow-planes.d.ts",
+ "backend/dist/services/traffic-flow-planes.d.ts.map",
+ "backend/dist/services/traffic-flow-purge-execution.js",
+ "backend/dist/services/traffic-flow-purge-execution.js.map",
+ "backend/dist/services/traffic-flow-purge-execution.d.ts",
+ "backend/dist/services/traffic-flow-purge-execution.d.ts.map",
+ "backend/dist/services/traffic-flow-ripe.js",
+ "backend/dist/services/traffic-flow-ripe.js.map",
+ "backend/dist/services/traffic-flow-ripe.d.ts",
+ "backend/dist/services/traffic-flow-ripe.d.ts.map",
+ "backend/dist/services/traffic-flow-settings.js",
+ "backend/dist/services/traffic-flow-settings.js.map",
+ "backend/dist/services/traffic-flow-settings.d.ts",
+ "backend/dist/services/traffic-flow-settings.d.ts.map",
+ "backend/dist/services/traffic-flow-topology.js",
+ "backend/dist/services/traffic-flow-topology.js.map",
+ "backend/dist/services/traffic-flow-topology.d.ts",
+ "backend/dist/services/traffic-flow-topology.d.ts.map",
+ "backend/dist/services/traffic-flow-worker-shutdown.js",
+ "backend/dist/services/traffic-flow-worker-shutdown.js.map",
+ "backend/dist/services/traffic-flow-worker-shutdown.d.ts",
+ "backend/dist/services/traffic-flow-worker-shutdown.d.ts.map",
+ "backend/dist/services/traffic-rate.js",
+ "backend/dist/services/traffic-rate.js.map",
+ "backend/dist/services/traffic-rate.d.ts",
+ "backend/dist/services/traffic-rate.d.ts.map",
+ "backend/dist/services/traffic-users.js",
+ "backend/dist/services/traffic-users.js.map",
+ "backend/dist/services/traffic-users.d.ts",
+ "backend/dist/services/traffic-users.d.ts.map",
+ "backend/dist/services/uptime-collector.js",
+ "backend/dist/services/uptime-collector.js.map",
+ "backend/dist/services/uptime-collector.d.ts",
+ "backend/dist/services/uptime-collector.d.ts.map",
+ "backend/dist/services/uptime-probe-observations.js",
+ "backend/dist/services/uptime-probe-observations.js.map",
+ "backend/dist/services/uptime-probe-observations.d.ts",
+ "backend/dist/services/uptime-probe-observations.d.ts.map",
+ "backend/dist/services/uptime-speed-service.js",
+ "backend/dist/services/uptime-speed-service.js.map",
+ "backend/dist/services/uptime-speed-service.d.ts",
+ "backend/dist/services/uptime-speed-service.d.ts.map",
+ "backend/dist/services/vxlan-live.js",
+ "backend/dist/services/vxlan-live.js.map",
+ "backend/dist/services/vxlan-live.d.ts",
+ "backend/dist/services/vxlan-live.d.ts.map",
+ "backend/dist/services/wg-keys.js",
+ "backend/dist/services/wg-keys.js.map",
+ "backend/dist/services/wg-keys.d.ts",
+ "backend/dist/services/wg-keys.d.ts.map",
+ "backend/dist/services/wireguard-config.js",
+ "backend/dist/services/wireguard-config.js.map",
+ "backend/dist/services/wireguard-config.d.ts",
+ "backend/dist/services/wireguard-config.d.ts.map",
+ "backend/dist/services/wireguard-delete.js",
+ "backend/dist/services/wireguard-delete.js.map",
+ "backend/dist/services/wireguard-delete.d.ts",
+ "backend/dist/services/wireguard-delete.d.ts.map",
+ "backend/dist/services/wireguard-import-apply.js",
+ "backend/dist/services/wireguard-import-apply.js.map",
+ "backend/dist/services/wireguard-import-apply.d.ts",
+ "backend/dist/services/wireguard-import-apply.d.ts.map",
+ "backend/dist/services/wireguard-import-revision.js",
+ "backend/dist/services/wireguard-import-revision.js.map",
+ "backend/dist/services/wireguard-import-revision.d.ts",
+ "backend/dist/services/wireguard-import-revision.d.ts.map",
+ "backend/dist/services/wireguard-import.js",
+ "backend/dist/services/wireguard-import.js.map",
+ "backend/dist/services/wireguard-import.d.ts",
+ "backend/dist/services/wireguard-import.d.ts.map",
+ "backend/dist/services/wireguard-live.js",
+ "backend/dist/services/wireguard-live.js.map",
+ "backend/dist/services/wireguard-live.d.ts",
+ "backend/dist/services/wireguard-live.d.ts.map",
+ "backend/dist/services/wireguard-observed-values.js",
+ "backend/dist/services/wireguard-observed-values.js.map",
+ "backend/dist/services/wireguard-observed-values.d.ts",
+ "backend/dist/services/wireguard-observed-values.d.ts.map",
+ "backend/dist/services/wireguard-ros.js",
+ "backend/dist/services/wireguard-ros.js.map",
+ "backend/dist/services/wireguard-ros.d.ts",
+ "backend/dist/services/wireguard-ros.d.ts.map",
+ "backend/dist/test/pg.js",
+ "backend/dist/test/pg.js.map",
+ "backend/dist/test/pg.d.ts",
+ "backend/dist/test/pg.d.ts.map",
+ "backend/dist/types/scheduler-run-snapshot.js",
+ "backend/dist/types/scheduler-run-snapshot.js.map",
+ "backend/dist/types/scheduler-run-snapshot.d.ts",
+ "backend/dist/types/scheduler-run-snapshot.d.ts.map",
+ "backend/dist/types/server.js",
+ "backend/dist/types/server.js.map",
+ "backend/dist/types/server.d.ts",
+ "backend/dist/types/server.d.ts.map",
+ "backend/dist/utils/abort-signals.js",
+ "backend/dist/utils/abort-signals.js.map",
+ "backend/dist/utils/abort-signals.d.ts",
+ "backend/dist/utils/abort-signals.d.ts.map",
+ "backend/dist/utils/ros-src-address.js",
+ "backend/dist/utils/ros-src-address.js.map",
+ "backend/dist/utils/ros-src-address.d.ts",
+ "backend/dist/utils/ros-src-address.d.ts.map",
+ "backend/dist/utils/server-id.js",
+ "backend/dist/utils/server-id.js.map",
+ "backend/dist/utils/server-id.d.ts",
+ "backend/dist/utils/server-id.d.ts.map",
+ "packages/contracts/dist/alerts.js",
+ "packages/contracts/dist/alerts.js.map",
+ "packages/contracts/dist/alerts.d.ts",
+ "packages/contracts/dist/alerts.d.ts.map",
+ "packages/contracts/dist/backups.js",
+ "packages/contracts/dist/backups.js.map",
+ "packages/contracts/dist/backups.d.ts",
+ "packages/contracts/dist/backups.d.ts.map",
+ "packages/contracts/dist/certificates.js",
+ "packages/contracts/dist/certificates.js.map",
+ "packages/contracts/dist/certificates.d.ts",
+ "packages/contracts/dist/certificates.d.ts.map",
+ "packages/contracts/dist/containers.js",
+ "packages/contracts/dist/containers.js.map",
+ "packages/contracts/dist/containers.d.ts",
+ "packages/contracts/dist/containers.d.ts.map",
+ "packages/contracts/dist/events.js",
+ "packages/contracts/dist/events.js.map",
+ "packages/contracts/dist/events.d.ts",
+ "packages/contracts/dist/events.d.ts.map",
+ "packages/contracts/dist/evobgp.js",
+ "packages/contracts/dist/evobgp.js.map",
+ "packages/contracts/dist/evobgp.d.ts",
+ "packages/contracts/dist/evobgp.d.ts.map",
+ "packages/contracts/dist/geoip.js",
+ "packages/contracts/dist/geoip.js.map",
+ "packages/contracts/dist/geoip.d.ts",
+ "packages/contracts/dist/geoip.d.ts.map",
+ "packages/contracts/dist/index.js",
+ "packages/contracts/dist/index.js.map",
+ "packages/contracts/dist/index.d.ts",
+ "packages/contracts/dist/index.d.ts.map",
+ "packages/contracts/dist/ipsec.js",
+ "packages/contracts/dist/ipsec.js.map",
+ "packages/contracts/dist/ipsec.d.ts",
+ "packages/contracts/dist/ipsec.d.ts.map",
+ "packages/contracts/dist/ospf-optimizer.js",
+ "packages/contracts/dist/ospf-optimizer.js.map",
+ "packages/contracts/dist/ospf-optimizer.d.ts",
+ "packages/contracts/dist/ospf-optimizer.d.ts.map",
+ "packages/contracts/dist/servers.js",
+ "packages/contracts/dist/servers.js.map",
+ "packages/contracts/dist/servers.d.ts",
+ "packages/contracts/dist/servers.d.ts.map",
+ "packages/contracts/dist/statistics.js",
+ "packages/contracts/dist/statistics.js.map",
+ "packages/contracts/dist/statistics.d.ts",
+ "packages/contracts/dist/statistics.d.ts.map",
+ "packages/contracts/dist/traffic-flow.js",
+ "packages/contracts/dist/traffic-flow.js.map",
+ "packages/contracts/dist/traffic-flow.d.ts",
+ "packages/contracts/dist/traffic-flow.d.ts.map",
+ "packages/contracts/dist/uptime-probes.js",
+ "packages/contracts/dist/uptime-probes.js.map",
+ "packages/contracts/dist/uptime-probes.d.ts",
+ "packages/contracts/dist/uptime-probes.d.ts.map",
+ "packages/contracts/dist/uptime-speed.js",
+ "packages/contracts/dist/uptime-speed.js.map",
+ "packages/contracts/dist/uptime-speed.d.ts",
+ "packages/contracts/dist/uptime-speed.d.ts.map",
+ "packages/contracts/dist/users.js",
+ "packages/contracts/dist/users.js.map",
+ "packages/contracts/dist/users.d.ts",
+ "packages/contracts/dist/users.d.ts.map",
+ "packages/contracts/dist/wireguard.js",
+ "packages/contracts/dist/wireguard.js.map",
+ "packages/contracts/dist/wireguard.d.ts",
+ "packages/contracts/dist/wireguard.d.ts.map",
+ "backend/dist/services/alert-engine/target-issues.js",
+ "backend/dist/services/alert-engine/target-issues.js.map",
+ "backend/dist/services/alert-engine/target-issues.d.ts",
+ "backend/dist/services/alert-engine/target-issues.d.ts.map"
+ ],
+ "missing": [],
+ "different": []
+}
\ No newline at end of file
diff --git a/docs/ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json b/docs/ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json
new file mode 100644
index 00000000..398859f6
--- /dev/null
+++ b/docs/ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json
@@ -0,0 +1,39 @@
+{
+ "date": "2026-10-12",
+ "block": "12.5.171",
+ "runtime": {
+ "backend": "ux-targets171",
+ "frontend": "ux-targets171"
+ },
+ "api200": true,
+ "ambiguousKindCount": 2,
+ "cases": [
+ {
+ "width": 1440,
+ "warningVisible": true,
+ "duplicateGrouped": true,
+ "serverLink": true,
+ "noOverflow": true,
+ "scopedAxeViolations": [],
+ "pageErrors": [],
+ "apiWrites": [],
+ "screenshot": "docs/ux-ui/screens/alerts-target-issues-1440-2026-10-12.png"
+ },
+ {
+ "width": 320,
+ "warningVisible": true,
+ "duplicateGrouped": true,
+ "serverLink": true,
+ "noOverflow": true,
+ "scopedAxeViolations": [],
+ "pageErrors": [],
+ "apiWrites": [],
+ "screenshot": "docs/ux-ui/screens/alerts-target-issues-320-2026-10-12.png"
+ }
+ ],
+ "bounds": [
+ "Read-only real duplicate CHR metadata; no rename/native mutation/password change/message",
+ "Scoped axe of new warning is not full WCAG certification",
+ "Disabled configuration covered by owned SQL and API-path UI fixtures; live configuration preserved"
+ ]
+}
diff --git a/docs/ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json b/docs/ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json
new file mode 100644
index 00000000..4e700296
--- /dev/null
+++ b/docs/ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json
@@ -0,0 +1,9 @@
+{
+ "date": "2026-10-12",
+ "block": "12.5.171",
+ "newFrontend": "ux-targets171",
+ "oldBackend": "ux-sources170",
+ "optionalDiagnosticMissing": true,
+ "readerAccepted": true,
+ "unknownDiagnosticNotInvented": true
+}
\ No newline at end of file
diff --git a/docs/ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json b/docs/ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json
new file mode 100644
index 00000000..8dbceed4
--- /dev/null
+++ b/docs/ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json
@@ -0,0 +1,30 @@
+{
+ "date": "2026-10-12",
+ "block": "12.5.171",
+ "services": {
+ "backend": {
+ "image": "mmapp-test/backend:ux-targets171",
+ "imageId": "sha256:754b7420ca35657fb566cec97cf37322320787363e1787bb4ce89aa0bfb256ed",
+ "matchedVerifiedImage": true,
+ "state": "running",
+ "health": "healthy"
+ },
+ "frontend": {
+ "image": "mmapp-test/frontend:ux-targets171",
+ "imageId": "sha256:050987e82c1ab5571f4c3dc8692a22f8ba703881f699c802f0168d90ab74652e",
+ "matchedVerifiedImage": true,
+ "state": "running",
+ "health": null
+ }
+ },
+ "rollbackTags": {
+ "MMAPP_IMAGE_TAG": "ux-bfd158",
+ "BACKEND_IMAGE_TAG": "ux-sources170"
+ },
+ "secretEnvCopied": false,
+ "runningContainers": [
+ "mmapp-test-backend",
+ "mmapp-test-frontend",
+ "mmapp-test-postgres"
+ ]
+}
\ No newline at end of file
diff --git a/docs/ux-ui/acceptance/alert-target-issues-source-2026-10-12.json b/docs/ux-ui/acceptance/alert-target-issues-source-2026-10-12.json
new file mode 100644
index 00000000..5f163e0d
--- /dev/null
+++ b/docs/ux-ui/acceptance/alert-target-issues-source-2026-10-12.json
@@ -0,0 +1,11 @@
+{
+ "date": "2026-10-12",
+ "block": "12.5.171",
+ "matched": {
+ "backend": 434,
+ "frontend": 518
+ },
+ "different": [],
+ "missing": [],
+ "sourceBase": "db7105119d0c9a3b1dee254d8e3d6ac45c97bba0"
+}
\ No newline at end of file
diff --git a/docs/ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json b/docs/ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json
new file mode 100644
index 00000000..09b5a607
--- /dev/null
+++ b/docs/ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json
@@ -0,0 +1,23 @@
+{
+ "date": "2026-10-12",
+ "block": "12.5.171",
+ "database": "mm_accept_166_1791794042576",
+ "scope": "ephemeral role and precreated owned database; no copied production credentials",
+ "tests": [
+ {
+ "command": "npm --prefix backend run test:alert-engine",
+ "passed": true,
+ "durationMs": 19540,
+ "ownedHistorySqlRows": 8,
+ "ownedSourceSqlCases": 16,
+ "sqlConfirmStabilityPassed": true,
+ "postgresUnavailableSkip": false
+ }
+ ],
+ "scopedRoleVerified": true,
+ "passed": true,
+ "databaseRemoved": true,
+ "roleRemoved": true,
+ "testContainerRemoved": true,
+ "metadataSqlAssertionsPassed": true
+}
\ No newline at end of file
diff --git a/docs/ux-ui/screens/alerts-target-issues-1440-2026-10-12.png b/docs/ux-ui/screens/alerts-target-issues-1440-2026-10-12.png
new file mode 100644
index 00000000..782bfbeb
Binary files /dev/null and b/docs/ux-ui/screens/alerts-target-issues-1440-2026-10-12.png differ
diff --git a/docs/ux-ui/screens/alerts-target-issues-320-2026-10-12.png b/docs/ux-ui/screens/alerts-target-issues-320-2026-10-12.png
new file mode 100644
index 00000000..aeebc3f4
Binary files /dev/null and b/docs/ux-ui/screens/alerts-target-issues-320-2026-10-12.png differ
diff --git a/packages/contracts/src/alerts.ts b/packages/contracts/src/alerts.ts
index d3b69d9f..09753a7c 100644
--- a/packages/contracts/src/alerts.ts
+++ b/packages/contracts/src/alerts.ts
@@ -93,9 +93,14 @@ export const alertRuleResponseSchema = z.object({
confirmStabilitySec:z.number().int().min(0).max(86400).nullable(),recoveryMode:recoveryModeSchema,recoveryStabilitySec:z.number().int().min(0).max(86400).nullable(),chatId:z.string(),lastFiredAt:alertTimestampSchema.nullable(),
}).strict()
export const alertHistoryResponseSchema = z.object({id:z.string().min(1),ruleName:z.string(),severity:alertSeveritySchema,message:z.string(),sent:z.boolean(),firedAt:alertTimestampSchema,source:z.enum(["db","live"])}).strict()
+export const alertTargetIssueSchema = z.object({
+ kind:z.enum(["server","traffic","probe"]),target:z.string().min(1),reason:z.enum(["ambiguous","disabled-object","disabled-source"]),
+}).strict()
+export type AlertTargetIssue=z.output
export const alertsMetaResponseSchema = z.object({
servers:z.array(z.string()),greClients:z.array(z.string()),probeTargets:z.array(z.string()),rttLossTargets:z.array(z.string()),trafficServers:z.array(z.string()),
serversDetail:z.array(z.object({name:z.string(),host:z.string(),site:z.string(),country:z.string(),type:z.string()}).strict()),
+ targetIssues:z.array(alertTargetIssueSchema).optional(),
}).strict()
const alertsConfigResponseShape = {groups:z.array(alertGroupSchema.strict()),rules:z.array(alertRuleResponseSchema)}
function validConfig(value:{groups:{id:string}[];rules:{id:string;groupId:string|null}[]}):boolean {
diff --git a/tests/e2e/alerts-target-issues.spec.ts b/tests/e2e/alerts-target-issues.spec.ts
new file mode 100644
index 00000000..53f09556
--- /dev/null
+++ b/tests/e2e/alerts-target-issues.spec.ts
@@ -0,0 +1,52 @@
+import {test,expect,type Page} from "@playwright/test"
+import {emptyAlerts,emptyOutbox} from "./fixtures/alerts"
+import type {AlertTargetIssue} from "@mmapp/contracts/alerts"
+async function setup(page:Page,reply:()=>unknown){
+ await page.route("**/health",r=>r.fulfill({json:{status:"ok"}}))
+ await page.route("**/api/**",r=>{const path=new URL(r.request().url()).pathname
+ if(path==="/api/auth/config")return r.fulfill({json:{required:false}})
+ if(path==="/api/alerts")return r.fulfill({json:reply()})
+ if(path==="/api/alerts/outbox")return r.fulfill({json:emptyOutbox})
+ if(path==="/api/servers"||path==="/api/bgp/sessions")return r.fulfill({json:[]})
+ if(path==="/api/filters/gre-tunnels")return r.fulfill({json:{tunnels:[]}})
+ return r.fulfill({status:503,json:{error:"outside diagnostic fixture"}})
+ })
+ await page.goto("/alerts")
+}
+for(const width of[1440,320])test(`Alerts targets: ambiguity is explained and grouped at ${width}`,async({page})=>{
+ await page.setViewportSize({width,height:1000})
+ const issues:AlertTargetIssue[]=[{kind:"server",target:"CHR",reason:"ambiguous"},{kind:"traffic",target:"CHR",reason:"ambiguous"}]
+ let current=issues
+ await setup(page,()=>({...emptyAlerts,meta:{...emptyAlerts.meta,targetIssues:current}}))
+ const warning=page.getByRole("status",{name:"Проблемы целей оповещений"})
+ await expect(warning).toBeVisible();await expect(warning.getByText("CHR",{exact:true})).toHaveCount(1)
+ await expect(warning).toContainText("Несколько включённых объектов")
+ await expect(warning).toContainText("обновите цели существующих правил")
+ await expect(warning.getByRole("link",{name:"Проверить серверы"})).toHaveAttribute("href","/servers")
+ expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
+ current=[];await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(warning).toHaveCount(0)
+})
+test("Alerts targets: disabled source and probe explain the next action",async({page})=>{
+ await setup(page,()=>({...emptyAlerts,meta:{...emptyAlerts.meta,targetIssues:[{kind:"traffic",target:"router",reason:"disabled-source"},{kind:"probe",target:"probe → target",reason:"disabled-object"}]}}))
+ const warning=page.getByRole("status",{name:"Проблемы целей оповещений"})
+ await expect(warning).toContainText("Сбор данных этого типа выключен")
+ await expect(warning).toContainText("Объект или его сервер выключен")
+ await expect(warning.getByRole("link",{name:"Проверить сбор данных"})).toHaveAttribute("href","/data-collection")
+ await expect(warning.getByRole("link",{name:"Проверить пробы"})).toHaveAttribute("href","/uptime")
+})
+test("Alerts targets: older valid API does not invent diagnostics",async({page})=>{
+ await setup(page,()=>emptyAlerts)
+ await expect(page.getByText("Всего: 0",{exact:true})).toBeVisible()
+ await expect(page.getByRole("status",{name:"Проблемы целей оповещений"})).toHaveCount(0)
+})
+test("Alerts targets: many long labels remain compact and keyboard accessible on phone",async({page})=>{
+ await page.setViewportSize({width:320,height:1000})
+ const targets=Array.from({length:6},(_,index)=>`target-${index}-${"x".repeat(180)}`)
+ await setup(page,()=>({...emptyAlerts,meta:{...emptyAlerts.meta,targetIssues:targets.map(target=>({kind:"server",target,reason:"ambiguous"}))}}))
+ const warning=page.getByRole("status",{name:"Проблемы целей оповещений"})
+ await expect(warning.getByText(targets[0],{exact:true})).toBeHidden()
+ const summary=warning.locator("summary");await summary.focus();await page.keyboard.press("Enter")
+ await expect(warning.getByText(targets[0],{exact:true})).toBeVisible()
+ expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
+ await page.keyboard.press("Enter");await expect(warning.getByText(targets[0],{exact:true})).toBeHidden()
+})