From 7d86af7e8b682673c57f048f1529b2e4720bd45a Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 13 Oct 2026 21:23:51 +0700 Subject: [PATCH] =?UTF-8?q?fix(auth):=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=20JWT=20=D1=87?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B7=20=D0=B7=D0=B0=D0=BA=D0=BE=D0=B4=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 2 +- backend/scripts/acceptance/auth-path-sql.mjs | 19 + backend/src/index.ts | 10 +- backend/src/lib/permissions.ts | 8 +- backend/src/plugins/auth-path.test.ts | 16 + backend/src/plugins/auth.ts | 9 +- docs/ux-ui-external-acceptance.md | 17 +- docs/ux-ui-plan.md | 2 +- docs/ux-ui-progress.md | 16 +- docs/ux-ui-remaining-acceptance.md | 23 +- docs/ux-ui-stage-12.md | 17 +- docs/ux-ui-test-server.md | 17 +- .../auth211-baseline-live-2026-10-13.json | 30 + .../auth211-deployment-2026-10-13.json | 24 + .../acceptance/auth211-live-2026-10-13.json | 193 +++ .../acceptance/auth211-production-result.json | 195 +++ .../auth211-profile-2026-10-13.json | 13 + docs/ux-ui/acceptance/compiled211-result.json | 1058 +++++++++++++++++ docs/ux-ui/acceptance/source211-result.json | 10 + 19 files changed, 1656 insertions(+), 23 deletions(-) create mode 100644 backend/scripts/acceptance/auth-path-sql.mjs create mode 100644 backend/src/plugins/auth-path.test.ts create mode 100644 docs/ux-ui/acceptance/auth211-baseline-live-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/auth211-deployment-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/auth211-live-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/auth211-production-result.json create mode 100644 docs/ux-ui/acceptance/auth211-profile-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/compiled211-result.json create mode 100644 docs/ux-ui/acceptance/source211-result.json diff --git a/backend/package.json b/backend/package.json index 9ab61d55..bfb96aeb 100644 --- a/backend/package.json +++ b/backend/package.json @@ -17,7 +17,7 @@ "facts:rebuild": "tsx src/scripts/rebuild-flow-facts.ts", "test:probes": "tsx src/routes/probes.test.ts && tsx src/routes/probes.cancel.test.ts && tsx src/services/ping-measurement.test.ts && tsx src/services/uptime-probe-observations.test.ts && tsx src/services/ping-measurement-sql.test.ts", "test:exec": "tsx src/services/mikrotik-logs.test.ts && tsx src/routes/exec.test.ts && tsx src/plugins/auth.exec.test.ts", - "test:auth": "tsx src/lib/permissions.test.ts && tsx src/plugins/auth.smoke.test.ts && tsx src/plugins/auth.ospf-optimizer.test.ts", + "test:auth": "tsx src/plugins/auth-path.test.ts && tsx src/lib/permissions.test.ts && tsx src/plugins/auth.smoke.test.ts && tsx src/plugins/auth.ospf-optimizer.test.ts", "test:wireguard": "npx tsx src/services/wireguard-config.test.ts && npx tsx src/services/wireguard-ipv6.test.ts && npx tsx --test src/services/wireguard-import.test.ts src/services/wireguard-import-apply.test.ts src/services/wireguard-import-revision.test.ts src/services/wireguard-delete.test.ts && npx tsx src/routes/wireguard-import.test.ts", "test:traffic-rate": "tsx src/services/traffic-rate.test.ts && tsx src/services/traffic-observation.test.ts && tsx src/services/traffic-freshness.test.ts && tsx src/services/traffic-live.test.ts && tsx src/services/traffic-observation-sql.test.ts && tsx src/services/traffic-history-sql.test.ts && tsx src/services/traffic-live-sql.test.ts && tsx src/services/traffic-volume-sql.test.ts && tsx src/services/traffic-binding-status.test.ts && tsx src/services/traffic-status-sql.test.ts && tsx src/services/traffic-gap.test.ts && tsx src/services/traffic-identity.test.ts && tsx src/services/traffic-membership.test.ts && tsx src/services/traffic-aggregate-peak.test.ts && tsx src/services/traffic-users-cache.test.ts && tsx src/services/traffic-collection-lock.test.ts && tsx src/services/traffic-concurrency-sql.test.ts", "test:traffic-flow": "tsx src/routes/traffic-flow-query.test.ts && tsx src/services/traffic-flow-month.test.ts && tsx src/services/traffic-flow-parse.test.ts && tsx src/services/traffic-flow-ipv6-pipeline.test.ts && tsx src/services/traffic-flow-map-exporter.test.ts && tsx src/services/traffic-flow-ifaces.test.ts && tsx src/services/traffic-flow-ifindex.test.ts && tsx src/services/traffic-flow-dedup.test.ts && tsx src/services/traffic-flow-planes.test.ts && tsx src/services/traffic-flow-ip.test.ts && tsx src/services/traffic-flow-dest.test.ts && tsx src/services/traffic-flow-classify.test.ts && tsx src/services/traffic-flow-ripe.test.ts && tsx src/services/traffic-flow-brands.test.ts && tsx src/services/traffic-flow-ingest.test.ts && tsx src/services/traffic-flow-analytics.test.ts && tsx src/services/traffic-flow-map-hops.test.ts && tsx src/services/traffic-flow-purge.test.ts && tsx src/services/traffic-flow-geoip.test.ts && tsx src/services/traffic-flow-facts.test.ts && tsx src/services/traffic-flow-facts-filter.test.ts && tsx src/services/traffic-flow-facts-rebuild.test.ts && tsx src/services/statistics-aggregate.test.ts", diff --git a/backend/scripts/acceptance/auth-path-sql.mjs b/backend/scripts/acceptance/auth-path-sql.mjs new file mode 100644 index 00000000..32007f0f --- /dev/null +++ b/backend/scripts/acceptance/auth-path-sql.mjs @@ -0,0 +1,19 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import {createServer} from 'node:http' +import {randomBytes} from 'node:crypto' +const database=process.env.MMAPP_OWN_SQL_DB,url=new URL(process.env.DATABASE_URL) +assert(/^mm_accept_166_\d+$/.test(database??''));assert.equal(url.pathname,'/'+database);assert.equal(url.username,database) +process.env.AUTH_REQUIRED='true';process.env.AUTH_JWT_SECRET=randomBytes(32).toString('hex');process.env.AUTH_ISSUER='https://own211.invalid';process.env.AUTH_PORTAL_URL='https://own211.invalid' +const {pool,closePool}=await import('/app/backend/dist/db/index.js'),{initDatabase}=await import('/app/backend/dist/db/bootstrap.js'),{buildApp}=await import('/app/backend/dist/index.js') +assert.equal((await pool.query('SELECT current_database() AS name')).rows[0].name,database);assert(Object.values((await pool.query('SELECT rolsuper,rolcreatedb,rolcreaterole,rolbypassrls FROM pg_roles WHERE rolname=current_user')).rows[0]).every(v=>v===false)) +const psk='own211-'+randomBytes(24).toString('base64url'),baseline=false,cases=[];let app,serverId,nativeWrites=0,nativeCalls=0 +const native=createServer((req,res)=>{nativeCalls++;if(req.method!=='GET')nativeWrites++;res.setHeader('content-type','application/json');res.end(JSON.stringify(req.url.endsWith('/interface/gre')?[{'.id':'*1',name:'own211-encrypted','local-address':'192.0.2.1','remote-address':'192.0.2.2','ipsec-secret':psk,mtu:'1476',keepalive:'10s,3',disabled:'false',running:'true','allow-fast-path':'false'},{'.id':'*2',name:'own211-plain','remote-address':'192.0.2.3','ipsec-secret':'',disabled:'false',running:'true'}]:[]))});await new Promise(r=>native.listen(0,'127.0.0.1',r)) +const report={date:'2026-10-13',block:'12.5.211',database,baseline,cases,scope:'Production compiled canonical auth/RBAC using own restricted PostgreSQL, local native HTTP fixture and synthetic JWT/PSK',passed:false} +try{await initDatabase();serverId=Number((await pool.query("INSERT INTO servers(name,host,port,use_ssl,enabled,username,password) VALUES('own211-native','127.0.0.1',$1,false,true,'fixture','fixture') RETURNING id",[native.address().port])).rows[0].id);app=await buildApp({logger:false,startScheduler:false});await app.ready() +for(const path of ['/api/servers','/api/%73ervers','/%61pi/servers','/%61%70%69/servers','/api/gre/tunnels','/%61pi/gre/tunnels'])for(const method of ['GET','HEAD']){const before=nativeCalls;const r=await app.inject({method,url:path});assert.equal(r.statusCode,401);assert.equal(nativeCalls,before);cases.push({path,method,role:'anonymous',status:401})} +for(const path of ['/api/gre/tunnels','/api/%67re/tunnels','/%61pi/gre/tunnels'])for(const role of ['dashboard','reader','writer']){const permissions=role==='dashboard'?['mm:dashboard:read']:role==='reader'?['mm:network:read']:['mm:network:write'],token=app.jwt.sign({sub:'own211-'+role,apps:['mm'],permissions,iss:process.env.AUTH_ISSUER},{expiresIn:'5m'});const r=await app.inject({method:'GET',url:path+'?serverId='+serverId,headers:{authorization:'Bearer '+token}});assert.equal(r.statusCode,role==='dashboard'?403:200);if(role!=='dashboard')assert.equal(r.json().tunnels.find(t=>t.name==='own211-encrypted').ipsec.secret,role==='writer'?psk:'');cases.push({path,method:'GET',role,status:r.statusCode,privateMaterialStored:false});if(role!=='writer'){const patch=await app.inject({method:'PATCH',url:path,headers:{authorization:'Bearer '+token},payload:{serverId:String(serverId),rosId:'*1',comment:'not applied'}});assert.equal(patch.statusCode,403);cases.push({path,method:'PATCH',role,status:403})}} +for(const path of ['/api/auth/config','/%61pi/auth/config']){assert.equal((await app.inject({url:path})).statusCode,200);cases.push({path,role:'anonymous',status:200,publicConfig:true})} +assert.equal(nativeWrites,0);report.nativeWrites=0;report.passed=true +}catch(e){report.errorName=e.name;fs.writeFileSync('/app/backend/acceptance/gre211-private.log',String(e.stack??e),{mode:0o600})}finally{if(app)await app.close();native.closeAllConnections();await new Promise(r=>native.close(r));await closePool();fs.writeFileSync('/app/backend/acceptance/auth211-production-result.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report))} +if(!report.passed)process.exitCode=1 diff --git a/backend/src/index.ts b/backend/src/index.ts index fac53695..8880a0ce 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -5,7 +5,7 @@ import { monitorEventLoopDelay } from "node:perf_hooks" import { env } from "./config.js" import { initDatabase } from "./db/bootstrap.js" import { closePool } from "./db/index.js" -import authPlugin, { requireAuth } from "./plugins/auth.js" +import authPlugin, { requireApiAuth } from "./plugins/auth.js" import { installDatabaseRequestGate } from "./plugins/database-request-gate.js" import serversRoutes from "./routes/servers.js" import bgpRoutes from "./routes/bgp.js" @@ -108,13 +108,7 @@ export async function buildApp(opts?: { })) if (env.authRequired) { - app.addHook("preHandler", async (request, reply) => { - const pathname = request.url.split("?")[0] ?? request.url - if (!pathname.startsWith("/api/")) return - if (pathname === "/api/auth/config") return - await requireAuth(request, reply) - if (reply.sent) return - }) + app.addHook("preHandler", requireApiAuth) } installDatabaseRequestGate(app) diff --git a/backend/src/lib/permissions.ts b/backend/src/lib/permissions.ts index 9ad13982..411a4186 100644 --- a/backend/src/lib/permissions.ts +++ b/backend/src/lib/permissions.ts @@ -47,17 +47,17 @@ const RULES: Rule[] = [ { methods: ["PUT", "POST"], match: path => path === "/api/geoip" || path === "/api/geoip/update", permission: "mm:traffic:write" }, { methods: ["GET"], - match: p => /^\/api\/servers\/\d+\/ospf(?:\/|$)/.test(p), + match: p => /^\/api\/servers\/(?:\d+|:[A-Za-z]\w*)\/ospf(?:\/|$)/.test(p), permission: "mm:network:read", }, { methods: ["POST"], - match: p => /^\/api\/servers\/\d+\/ospf\/optimize\/preview$/.test(p), + match: p => /^\/api\/servers\/(?:\d+|:[A-Za-z]\w*)\/ospf\/optimize\/preview$/.test(p), permission: "mm:network:read", }, { methods: ["POST", "PUT", "PATCH", "DELETE"], - match: p => /^\/api\/servers\/\d+\/ospf(?:\/|$)/.test(p), + match: p => /^\/api\/servers\/(?:\d+|:[A-Za-z]\w*)\/ospf(?:\/|$)/.test(p), permission: "mm:network:write", }, @@ -201,7 +201,7 @@ export function permissionForRequest( method: string, path: string, ): string | null { - const m = method.toUpperCase() + const m = method.toUpperCase() === "HEAD" ? "GET" : method.toUpperCase() const pathname = path.split("?")[0] ?? path for (const rule of RULES) { if (!rule.methods.includes(m)) continue diff --git a/backend/src/plugins/auth-path.test.ts b/backend/src/plugins/auth-path.test.ts new file mode 100644 index 00000000..8db711b1 --- /dev/null +++ b/backend/src/plugins/auth-path.test.ts @@ -0,0 +1,16 @@ +import assert from 'node:assert/strict' +import Fastify from 'fastify' +process.env.AUTH_REQUIRED='true';process.env.AUTH_JWT_SECRET='own211-synthetic-secret';process.env.AUTH_ISSUER='https://own211.invalid';process.env.NODE_ENV='test' +const {default:authPlugin,requireApiAuth}=await import('./auth.js') +const app=Fastify();await app.register(authPlugin);app.addHook('preHandler',requireApiAuth);let calls=0 +for(const url of ['/api/servers','/api/gre/tunnels','/api/servers/:id/ospf'])app.get(url,async()=>{calls++;return{ok:true}}) +app.patch('/api/gre/tunnels',async()=>{calls++;return{ok:true}}) +app.post('/api/servers/:id/ospf/optimize/preview',async()=>{calls++;return{ok:true}}) +app.get('/api/auth/config',async()=>({public:true}));app.get('/health',async()=>({public:true}));await app.ready() +const token=(permissions:string[])=>app.jwt.sign({sub:'own211',apps:['mm'],permissions,iss:process.env.AUTH_ISSUER},{expiresIn:'5m'}) +let cases=0 +for(const url of ['/api/servers','/api/%73ervers','/%61pi/servers','/%61%70%69/%73ervers'])for(const method of ['GET','HEAD'] as const){const before=calls,r=await app.inject({method,url});assert.equal(r.statusCode,401,url);assert.equal(calls,before);cases++} +for(const url of ['/api/gre/tunnels','/api/%67re/tunnels','/%61pi/gre/tunnels'])for(const method of ['GET','HEAD','PATCH'] as const)for(const role of ['dashboard','reader','writer']){const before=calls,permissions=role==='dashboard'?['mm:dashboard:read']:role==='reader'?['mm:network:read']:['mm:network:write'],allowed=role==='writer'||(role==='reader'&&method!=='PATCH'),r=await app.inject({method,url,headers:{authorization:'Bearer '+token(permissions)}});assert.equal(r.statusCode,allowed?200:403,url+' '+method+' '+role);assert.equal(calls,before+(allowed?1:0));cases++} +for(const method of ['GET','POST'] as const){const url=method==='GET'?'/api/servers/1/ospf':'/api/servers/1/ospf/optimize/preview';assert.equal((await app.inject({method,url,headers:{authorization:'Bearer '+token(['mm:network:read'])}})).statusCode,200);assert.equal((await app.inject({method,url,headers:{authorization:'Bearer '+token(['mm:servers:read'])}})).statusCode,403);cases+=2} +for(const url of ['/health','/api/auth/config','/%61pi/auth/config']){assert.equal((await app.inject({url})).statusCode,200);cases++} +await app.close();console.log('Canonical API auth: '+cases+' cases, denied handlers not called, HEAD and OSPF matched templates preserved') diff --git a/backend/src/plugins/auth.ts b/backend/src/plugins/auth.ts index c4bd639f..27c3765f 100644 --- a/backend/src/plugins/auth.ts +++ b/backend/src/plugins/auth.ts @@ -74,7 +74,7 @@ export async function requireAuth( ): Promise { if (!env.authRequired) return - const pathname = (request.url.split("?")[0] ?? request.url) + const pathname = request.routeOptions.url ?? request.url.split("?")[0] ?? request.url if (pathname === "/api/auth/config") return const authHeader = request.headers.authorization ?? "" @@ -116,4 +116,11 @@ export async function requireAuth( } } +/** Gate the matched route, including encoded static segments in the raw URL. */ +export async function requireApiAuth(request: FastifyRequest, reply: FastifyReply): Promise { + const pathname = request.routeOptions.url ?? request.url.split("?")[0] ?? request.url + if (!pathname.startsWith("/api/") || pathname === "/api/auth/config") return + await requireAuth(request, reply) +} + export default fp(authPlugin, { name: "auth" }) diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 768a34e6..2dcc4bac 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-13: блок 210 завершён. GRE создаётся с default keepalive 10s,10; минутные значения читаются в секундах, PATCH другого поля сохраняет native timer. Валидатор каталога IPsec исправлен для Filters/карты/диагностики. Пройдены SQL/API14, E2E13 и live GRE/Filters UI4; собственные интерфейсы удалены. Backend/frontend ux-gre210, source475/527 и compiled1048 совпали. Срочный следующий блок 211 — auth/RBAC для закодированных URL; baseline анонимного обхода подтверждён. Этап 12.5 открыт. +Актуальное продолжение 2026-10-13: блок 211 завершён. Закрыт анонимный обход JWT и section RBAC через encoded URL: проверяется маршрут Fastify, HEAD наследует GET policy, OSPF parameter routes сохраняют права. Пройдены auth42, production SQL/API29 и live26; тестовые DB/role/users удалены. Backend ux-auth211/source477/compiled1048, frontend ux-gre210. Следующий212 — совместимость GRE FastPath/PSK и шаблон экспорта недопустимого keepalive. Этап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). @@ -2556,3 +2556,18 @@ Runtime ux-gre210: backend healthy, source475/527 и compiled1048 matched. На Протоколы: [native syntax](ux-ui/acceptance/gre210-native-range-2026-10-13.json), [дополнительный синтаксис](ux-ui/acceptance/gre210-native-range-extra-2026-10-13.json), [SQL/API14](ux-ui/acceptance/gre210-keepalive-result.json), [профили](ux-ui/acceptance/gre210-profile-2026-10-13.json), [E2E13](ux-ui/acceptance/gre210-e2e-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre210-native-live-2026-10-13.json), [source](ux-ui/acceptance/source210-result.json), [compiled](ux-ui/acceptance/compiled210-result.json), [deployment](ux-ui/acceptance/gre210-deployment-2026-10-13.json). + +## 12.5.211 — JWT/RBAC для закодированных URL (2026-10-13) + +Actual baseline: обычный /api/servers без JWT возвращал401, но /%61pi/servers возвращал200 и server rows с непустыми паролями. Fastify распознаёт encoded static segments; middleware сравнивал raw URL и пропускал auth для encoded /api prefix. Для encoded имени раздела можно было также получить fallback dashboard permission. В evidence сохранены только статусы, число строк и boolean наличия пароля; raw body, credentials и JWT не сохранялись и не выводились. + +Общий preHandler и requireAuth теперь используют request.routeOptions.url — фактически выбранный Fastify маршрут. Проверка public auth config/health сохранена; percent decoding не выполняется повторно вручную. Permission mapping OSPF принимает доверенные parameter templates наряду с прежними numeric paths; HEAD получает те же read permissions, что GET. Политики ролей и AUTH_REQUIRED=false не расширены. Frontend и RouterOS конфигурация не менялись. + +42 канонических auth fixtures: encoded static prefix/раздел, GET/HEAD/PATCH, denied handler count0, OSPF reader/preview и servers-only denial, public config/health. Прежние test:auth, GeoIP JWT и NetFlow private export guards прошли; backend build прошёл. Изменена общая auth-основа, поэтому добавлены профильные проверки разных ресурсов и параметризованных маршрутов; полный UI regression192 не повторялся для backend-only изменения. + +Production compiled SQL/API29 на собственной ограниченной DB/role: anonymous401, dashboard-only403, network reader/writer GET и PSK redaction, denied PATCH403 до native, public config200. Native writes0; DB/role/container удалены. Backend ux-auth211 развёрнут healthy; source477 и compiled1048 совпали. Frontend ux-gre210 сохранён. Live26 с настоящими Portal JWT: анонимные GET/HEAD401, обычные/encoded server и GRE GET по ролям, пустой PATCH403. Пустое тело гарантирует отсутствие native apply даже при ошибке защиты. Два временных Portal user удалены; секреты не публиковались. Пароли CHR не менялись. + +Протоколы: [actual baseline](ux-ui/acceptance/auth211-baseline-live-2026-10-13.json), [профиль](ux-ui/acceptance/auth211-profile-2026-10-13.json), [production SQL/API29](ux-ui/acceptance/auth211-production-result.json), [live26](ux-ui/acceptance/auth211-live-2026-10-13.json), [source](ux-ui/acceptance/source211-result.json), [compiled](ux-ui/acceptance/compiled211-result.json), [deployment](ux-ui/acceptance/auth211-deployment-2026-10-13.json). + +Следующий212: GRE create с PSK и опущенным FastPath, explicit incompatible combination, экспорт недопустимого/неизвестного keepalive. 12.5 остаётся открытой по внешней матрице. + diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 99a86e5f..2d497157 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,6 +1,6 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-13: блок 210 завершён. GRE создаётся с default keepalive 10s,10; минутные значения читаются в секундах, PATCH другого поля сохраняет native timer. Валидатор каталога IPsec исправлен для Filters/карты/диагностики. Пройдены SQL/API14, E2E13 и live GRE/Filters UI4; собственные интерфейсы удалены. Backend/frontend ux-gre210, source475/527 и compiled1048 совпали. Срочный следующий блок 211 — auth/RBAC для закодированных URL; baseline анонимного обхода подтверждён. Этап 12.5 открыт. +Актуальное продолжение 2026-10-13: блок 211 завершён. Закрыт анонимный обход JWT и section RBAC через encoded URL: проверяется маршрут Fastify, HEAD наследует GET policy, OSPF parameter routes сохраняют права. Пройдены auth42, production SQL/API29 и live26; тестовые DB/role/users удалены. Backend ux-auth211/source477/compiled1048, frontend ux-gre210. Следующий212 — совместимость GRE FastPath/PSK и шаблон экспорта недопустимого keepalive. Этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-13. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index cecfab36..5778ece1 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-13: блок 210 завершён. GRE создаётся с default keepalive 10s,10; минутные значения читаются в секундах, PATCH другого поля сохраняет native timer. Валидатор каталога IPsec исправлен для Filters/карты/диагностики. Пройдены SQL/API14, E2E13 и live GRE/Filters UI4; собственные интерфейсы удалены. Backend/frontend ux-gre210, source475/527 и compiled1048 совпали. Срочный следующий блок 211 — auth/RBAC для закодированных URL; baseline анонимного обхода подтверждён. Этап 12.5 открыт. +Актуальное продолжение 2026-10-13: блок 211 завершён. Закрыт анонимный обход JWT и section RBAC через encoded URL: проверяется маршрут Fastify, HEAD наследует GET policy, OSPF parameter routes сохраняют права. Пройдены auth42, production SQL/API29 и live26; тестовые DB/role/users удалены. Backend ux-auth211/source477/compiled1048, frontend ux-gre210. Следующий212 — совместимость GRE FastPath/PSK и шаблон экспорта недопустимого keepalive. Этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -38,6 +38,20 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–196 и ограничения ниже. Runtime backend/frontend ux-peak196. | +## 12.5.211 — JWT/RBAC для закодированных URL (2026-10-13) + +Actual baseline: обычный /api/servers без JWT возвращал401, но /%61pi/servers возвращал200 и server rows с непустыми паролями. Fastify распознаёт encoded static segments; middleware сравнивал raw URL и пропускал auth для encoded /api prefix. Для encoded имени раздела можно было также получить fallback dashboard permission. В evidence сохранены только статусы, число строк и boolean наличия пароля; raw body, credentials и JWT не сохранялись и не выводились. + +Общий preHandler и requireAuth теперь используют request.routeOptions.url — фактически выбранный Fastify маршрут. Проверка public auth config/health сохранена; percent decoding не выполняется повторно вручную. Permission mapping OSPF принимает доверенные parameter templates наряду с прежними numeric paths; HEAD получает те же read permissions, что GET. Политики ролей и AUTH_REQUIRED=false не расширены. Frontend и RouterOS конфигурация не менялись. + +42 канонических auth fixtures: encoded static prefix/раздел, GET/HEAD/PATCH, denied handler count0, OSPF reader/preview и servers-only denial, public config/health. Прежние test:auth, GeoIP JWT и NetFlow private export guards прошли; backend build прошёл. Изменена общая auth-основа, поэтому добавлены профильные проверки разных ресурсов и параметризованных маршрутов; полный UI regression192 не повторялся для backend-only изменения. + +Production compiled SQL/API29 на собственной ограниченной DB/role: anonymous401, dashboard-only403, network reader/writer GET и PSK redaction, denied PATCH403 до native, public config200. Native writes0; DB/role/container удалены. Backend ux-auth211 развёрнут healthy; source477 и compiled1048 совпали. Frontend ux-gre210 сохранён. Live26 с настоящими Portal JWT: анонимные GET/HEAD401, обычные/encoded server и GRE GET по ролям, пустой PATCH403. Пустое тело гарантирует отсутствие native apply даже при ошибке защиты. Два временных Portal user удалены; секреты не публиковались. Пароли CHR не менялись. + +Протоколы: [actual baseline](ux-ui/acceptance/auth211-baseline-live-2026-10-13.json), [профиль](ux-ui/acceptance/auth211-profile-2026-10-13.json), [production SQL/API29](ux-ui/acceptance/auth211-production-result.json), [live26](ux-ui/acceptance/auth211-live-2026-10-13.json), [source](ux-ui/acceptance/source211-result.json), [compiled](ux-ui/acceptance/compiled211-result.json), [deployment](ux-ui/acceptance/auth211-deployment-2026-10-13.json). + +Следующий212: GRE create с PSK и опущенным FastPath, explicit incompatible combination, экспорт недопустимого/неизвестного keepalive. 12.5 остаётся открытой по внешней матрице. + ## 12.5.210 — GRE keepalive и совместимость публичного каталога (2026-10-13) На обоих CHR собственные отключённые интерфейсы подтвердили: native REST отклоняет 0, none, пустую строку, disabled, no и ноль попыток. Дробные интервалы принимаются, но сокращаются RouterOS до целых секунд. Поэтому форма и write schema требуют целые значения 1..4294967295 вместо обещания «0 = откл.». Неверный ввод сохраняет форму и не отправляет запрос. Официальный default 10s,10: [MikroTik GRE](https://help.mikrotik.com/docs/spaces/ROS/pages/24805531/GRE). diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index 9940b60b..c1c8a1e2 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,10 +1,10 @@ # Оставшаяся внешняя приёмка — 2026-10-13 -Актуальное продолжение 2026-10-13: блок 210 завершён. GRE создаётся с default keepalive 10s,10; минутные значения читаются в секундах, PATCH другого поля сохраняет native timer. Валидатор каталога IPsec исправлен для Filters/карты/диагностики. Пройдены SQL/API14, E2E13 и live GRE/Filters UI4; собственные интерфейсы удалены. Backend/frontend ux-gre210, source475/527 и compiled1048 совпали. Срочный следующий блок 211 — auth/RBAC для закодированных URL; baseline анонимного обхода подтверждён. Этап 12.5 открыт. +Актуальное продолжение 2026-10-13: блок 211 завершён. Закрыт анонимный обход JWT и section RBAC через encoded URL: проверяется маршрут Fastify, HEAD наследует GET policy, OSPF parameter routes сохраняют права. Пройдены auth42, production SQL/API29 и live26; тестовые DB/role/users удалены. Backend ux-auth211/source477/compiled1048, frontend ux-gre210. Следующий212 — совместимость GRE FastPath/PSK и шаблон экспорта недопустимого keepalive. Этап12.5 открыт. -Это актуальная матрица после 12.5.210. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.211. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend/frontend `ux-gre210`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-auth211`, frontend `ux-gre210`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | @@ -26,7 +26,7 @@ ## Следующая последовательность — 2026-10-13 -1. **211 — canonical auth path:** закрыть обход JWT/RBAC через encoded API prefix; actual anonymous baseline200 сохранён без raw body/секретов. После него — FastPath/PSK default и экспорт неизвестного keepalive. +1. **212 — GRE compatibility:** PSK/FastPath default и explicit conflict; экспорт недопустимого/неизвестного keepalive. Canonical auth/RBAC211 закрыт и развёрнут. 2. **Профильный контроль:** для новых изменений выполнять затронутые SQL/API/UI проверки. Общая регрессия192 выполнена; не повторять её без изменений общей основы или нового основания. 3. **Внешние зависимости:** Portal issuer/login/revoke, Telegram bot/chat/разрешённое сообщение, клиентские ОС, независимые WAN/public IPv6 и scale/multi-instance — отдельные группы по таблице выше. Ограничения текущего стенда не превращать в обещание приёмки всех конфигураций. @@ -1474,3 +1474,18 @@ Runtime ux-gre210: backend healthy, source475/527 и compiled1048 matched. На Протоколы: [native syntax](ux-ui/acceptance/gre210-native-range-2026-10-13.json), [дополнительный синтаксис](ux-ui/acceptance/gre210-native-range-extra-2026-10-13.json), [SQL/API14](ux-ui/acceptance/gre210-keepalive-result.json), [профили](ux-ui/acceptance/gre210-profile-2026-10-13.json), [E2E13](ux-ui/acceptance/gre210-e2e-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre210-native-live-2026-10-13.json), [source](ux-ui/acceptance/source210-result.json), [compiled](ux-ui/acceptance/compiled210-result.json), [deployment](ux-ui/acceptance/gre210-deployment-2026-10-13.json). + +## 12.5.211 — JWT/RBAC для закодированных URL (2026-10-13) + +Actual baseline: обычный /api/servers без JWT возвращал401, но /%61pi/servers возвращал200 и server rows с непустыми паролями. Fastify распознаёт encoded static segments; middleware сравнивал raw URL и пропускал auth для encoded /api prefix. Для encoded имени раздела можно было также получить fallback dashboard permission. В evidence сохранены только статусы, число строк и boolean наличия пароля; raw body, credentials и JWT не сохранялись и не выводились. + +Общий preHandler и requireAuth теперь используют request.routeOptions.url — фактически выбранный Fastify маршрут. Проверка public auth config/health сохранена; percent decoding не выполняется повторно вручную. Permission mapping OSPF принимает доверенные parameter templates наряду с прежними numeric paths; HEAD получает те же read permissions, что GET. Политики ролей и AUTH_REQUIRED=false не расширены. Frontend и RouterOS конфигурация не менялись. + +42 канонических auth fixtures: encoded static prefix/раздел, GET/HEAD/PATCH, denied handler count0, OSPF reader/preview и servers-only denial, public config/health. Прежние test:auth, GeoIP JWT и NetFlow private export guards прошли; backend build прошёл. Изменена общая auth-основа, поэтому добавлены профильные проверки разных ресурсов и параметризованных маршрутов; полный UI regression192 не повторялся для backend-only изменения. + +Production compiled SQL/API29 на собственной ограниченной DB/role: anonymous401, dashboard-only403, network reader/writer GET и PSK redaction, denied PATCH403 до native, public config200. Native writes0; DB/role/container удалены. Backend ux-auth211 развёрнут healthy; source477 и compiled1048 совпали. Frontend ux-gre210 сохранён. Live26 с настоящими Portal JWT: анонимные GET/HEAD401, обычные/encoded server и GRE GET по ролям, пустой PATCH403. Пустое тело гарантирует отсутствие native apply даже при ошибке защиты. Два временных Portal user удалены; секреты не публиковались. Пароли CHR не менялись. + +Протоколы: [actual baseline](ux-ui/acceptance/auth211-baseline-live-2026-10-13.json), [профиль](ux-ui/acceptance/auth211-profile-2026-10-13.json), [production SQL/API29](ux-ui/acceptance/auth211-production-result.json), [live26](ux-ui/acceptance/auth211-live-2026-10-13.json), [source](ux-ui/acceptance/source211-result.json), [compiled](ux-ui/acceptance/compiled211-result.json), [deployment](ux-ui/acceptance/auth211-deployment-2026-10-13.json). + +Следующий212: GRE create с PSK и опущенным FastPath, explicit incompatible combination, экспорт недопустимого/неизвестного keepalive. 12.5 остаётся открытой по внешней матрице. + diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 17d0e056..928cba8d 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-13: блок 210 завершён. GRE создаётся с default keepalive 10s,10; минутные значения читаются в секундах, PATCH другого поля сохраняет native timer. Валидатор каталога IPsec исправлен для Filters/карты/диагностики. Пройдены SQL/API14, E2E13 и live GRE/Filters UI4; собственные интерфейсы удалены. Backend/frontend ux-gre210, source475/527 и compiled1048 совпали. Срочный следующий блок 211 — auth/RBAC для закодированных URL; baseline анонимного обхода подтверждён. Этап 12.5 открыт. +Актуальное продолжение 2026-10-13: блок 211 завершён. Закрыт анонимный обход JWT и section RBAC через encoded URL: проверяется маршрут Fastify, HEAD наследует GET policy, OSPF parameter routes сохраняют права. Пройдены auth42, production SQL/API29 и live26; тестовые DB/role/users удалены. Backend ux-auth211/source477/compiled1048, frontend ux-gre210. Следующий212 — совместимость GRE FastPath/PSK и шаблон экспорта недопустимого keepalive. Этап12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -3863,3 +3863,18 @@ Runtime ux-gre210: backend healthy, source475/527 и compiled1048 matched. На Протоколы: [native syntax](ux-ui/acceptance/gre210-native-range-2026-10-13.json), [дополнительный синтаксис](ux-ui/acceptance/gre210-native-range-extra-2026-10-13.json), [SQL/API14](ux-ui/acceptance/gre210-keepalive-result.json), [профили](ux-ui/acceptance/gre210-profile-2026-10-13.json), [E2E13](ux-ui/acceptance/gre210-e2e-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre210-native-live-2026-10-13.json), [source](ux-ui/acceptance/source210-result.json), [compiled](ux-ui/acceptance/compiled210-result.json), [deployment](ux-ui/acceptance/gre210-deployment-2026-10-13.json). + +## 12.5.211 — JWT/RBAC для закодированных URL (2026-10-13) + +Actual baseline: обычный /api/servers без JWT возвращал401, но /%61pi/servers возвращал200 и server rows с непустыми паролями. Fastify распознаёт encoded static segments; middleware сравнивал raw URL и пропускал auth для encoded /api prefix. Для encoded имени раздела можно было также получить fallback dashboard permission. В evidence сохранены только статусы, число строк и boolean наличия пароля; raw body, credentials и JWT не сохранялись и не выводились. + +Общий preHandler и requireAuth теперь используют request.routeOptions.url — фактически выбранный Fastify маршрут. Проверка public auth config/health сохранена; percent decoding не выполняется повторно вручную. Permission mapping OSPF принимает доверенные parameter templates наряду с прежними numeric paths; HEAD получает те же read permissions, что GET. Политики ролей и AUTH_REQUIRED=false не расширены. Frontend и RouterOS конфигурация не менялись. + +42 канонических auth fixtures: encoded static prefix/раздел, GET/HEAD/PATCH, denied handler count0, OSPF reader/preview и servers-only denial, public config/health. Прежние test:auth, GeoIP JWT и NetFlow private export guards прошли; backend build прошёл. Изменена общая auth-основа, поэтому добавлены профильные проверки разных ресурсов и параметризованных маршрутов; полный UI regression192 не повторялся для backend-only изменения. + +Production compiled SQL/API29 на собственной ограниченной DB/role: anonymous401, dashboard-only403, network reader/writer GET и PSK redaction, denied PATCH403 до native, public config200. Native writes0; DB/role/container удалены. Backend ux-auth211 развёрнут healthy; source477 и compiled1048 совпали. Frontend ux-gre210 сохранён. Live26 с настоящими Portal JWT: анонимные GET/HEAD401, обычные/encoded server и GRE GET по ролям, пустой PATCH403. Пустое тело гарантирует отсутствие native apply даже при ошибке защиты. Два временных Portal user удалены; секреты не публиковались. Пароли CHR не менялись. + +Протоколы: [actual baseline](ux-ui/acceptance/auth211-baseline-live-2026-10-13.json), [профиль](ux-ui/acceptance/auth211-profile-2026-10-13.json), [production SQL/API29](ux-ui/acceptance/auth211-production-result.json), [live26](ux-ui/acceptance/auth211-live-2026-10-13.json), [source](ux-ui/acceptance/source211-result.json), [compiled](ux-ui/acceptance/compiled211-result.json), [deployment](ux-ui/acceptance/auth211-deployment-2026-10-13.json). + +Следующий212: GRE create с PSK и опущенным FastPath, explicit incompatible combination, экспорт недопустимого/неизвестного keepalive. 12.5 остаётся открытой по внешней матрице. + diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 8401ba36..49a2dec5 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-10 -Актуальное продолжение 2026-10-13: блок 210 завершён. GRE создаётся с default keepalive 10s,10; минутные значения читаются в секундах, PATCH другого поля сохраняет native timer. Валидатор каталога IPsec исправлен для Filters/карты/диагностики. Пройдены SQL/API14, E2E13 и live GRE/Filters UI4; собственные интерфейсы удалены. Backend/frontend ux-gre210, source475/527 и compiled1048 совпали. Срочный следующий блок 211 — auth/RBAC для закодированных URL; baseline анонимного обхода подтверждён. Этап 12.5 открыт. +Актуальное продолжение 2026-10-13: блок 211 завершён. Закрыт анонимный обход JWT и section RBAC через encoded URL: проверяется маршрут Fastify, HEAD наследует GET policy, OSPF parameter routes сохраняют права. Пройдены auth42, production SQL/API29 и live26; тестовые DB/role/users удалены. Backend ux-auth211/source477/compiled1048, frontend ux-gre210. Следующий212 — совместимость GRE FastPath/PSK и шаблон экспорта недопустимого keepalive. Этап12.5 открыт. | Параметр | Проверенное состояние | | --- | --- | @@ -2287,3 +2287,18 @@ Runtime ux-gre210: backend healthy, source475/527 и compiled1048 matched. На Протоколы: [native syntax](ux-ui/acceptance/gre210-native-range-2026-10-13.json), [дополнительный синтаксис](ux-ui/acceptance/gre210-native-range-extra-2026-10-13.json), [SQL/API14](ux-ui/acceptance/gre210-keepalive-result.json), [профили](ux-ui/acceptance/gre210-profile-2026-10-13.json), [E2E13](ux-ui/acceptance/gre210-e2e-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre210-native-live-2026-10-13.json), [source](ux-ui/acceptance/source210-result.json), [compiled](ux-ui/acceptance/compiled210-result.json), [deployment](ux-ui/acceptance/gre210-deployment-2026-10-13.json). + +## 12.5.211 — JWT/RBAC для закодированных URL (2026-10-13) + +Actual baseline: обычный /api/servers без JWT возвращал401, но /%61pi/servers возвращал200 и server rows с непустыми паролями. Fastify распознаёт encoded static segments; middleware сравнивал raw URL и пропускал auth для encoded /api prefix. Для encoded имени раздела можно было также получить fallback dashboard permission. В evidence сохранены только статусы, число строк и boolean наличия пароля; raw body, credentials и JWT не сохранялись и не выводились. + +Общий preHandler и requireAuth теперь используют request.routeOptions.url — фактически выбранный Fastify маршрут. Проверка public auth config/health сохранена; percent decoding не выполняется повторно вручную. Permission mapping OSPF принимает доверенные parameter templates наряду с прежними numeric paths; HEAD получает те же read permissions, что GET. Политики ролей и AUTH_REQUIRED=false не расширены. Frontend и RouterOS конфигурация не менялись. + +42 канонических auth fixtures: encoded static prefix/раздел, GET/HEAD/PATCH, denied handler count0, OSPF reader/preview и servers-only denial, public config/health. Прежние test:auth, GeoIP JWT и NetFlow private export guards прошли; backend build прошёл. Изменена общая auth-основа, поэтому добавлены профильные проверки разных ресурсов и параметризованных маршрутов; полный UI regression192 не повторялся для backend-only изменения. + +Production compiled SQL/API29 на собственной ограниченной DB/role: anonymous401, dashboard-only403, network reader/writer GET и PSK redaction, denied PATCH403 до native, public config200. Native writes0; DB/role/container удалены. Backend ux-auth211 развёрнут healthy; source477 и compiled1048 совпали. Frontend ux-gre210 сохранён. Live26 с настоящими Portal JWT: анонимные GET/HEAD401, обычные/encoded server и GRE GET по ролям, пустой PATCH403. Пустое тело гарантирует отсутствие native apply даже при ошибке защиты. Два временных Portal user удалены; секреты не публиковались. Пароли CHR не менялись. + +Протоколы: [actual baseline](ux-ui/acceptance/auth211-baseline-live-2026-10-13.json), [профиль](ux-ui/acceptance/auth211-profile-2026-10-13.json), [production SQL/API29](ux-ui/acceptance/auth211-production-result.json), [live26](ux-ui/acceptance/auth211-live-2026-10-13.json), [source](ux-ui/acceptance/source211-result.json), [compiled](ux-ui/acceptance/compiled211-result.json), [deployment](ux-ui/acceptance/auth211-deployment-2026-10-13.json). + +Следующий212: GRE create с PSK и опущенным FastPath, explicit incompatible combination, экспорт недопустимого/неизвестного keepalive. 12.5 остаётся открытой по внешней матрице. + diff --git a/docs/ux-ui/acceptance/auth211-baseline-live-2026-10-13.json b/docs/ux-ui/acceptance/auth211-baseline-live-2026-10-13.json new file mode 100644 index 00000000..e0587396 --- /dev/null +++ b/docs/ux-ui/acceptance/auth211-baseline-live-2026-10-13.json @@ -0,0 +1,30 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "runtime": "ux-gre209", + "cases": [ + { + "path": "/api/servers", + "status": 401, + "anonymous": true, + "serverRows": 0, + "nonemptyPasswordPresent": false + }, + { + "path": "/api/%73ervers", + "status": 401, + "anonymous": true, + "serverRows": 0, + "nonemptyPasswordPresent": false + }, + { + "path": "/%61pi/servers", + "status": 200, + "anonymous": true, + "serverRows": 2, + "nonemptyPasswordPresent": true + } + ], + "rawBodyStored": false, + "mutationRequests": 0 +} diff --git a/docs/ux-ui/acceptance/auth211-deployment-2026-10-13.json b/docs/ux-ui/acceptance/auth211-deployment-2026-10-13.json new file mode 100644 index 00000000..f540d671 --- /dev/null +++ b/docs/ux-ui/acceptance/auth211-deployment-2026-10-13.json @@ -0,0 +1,24 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "services": { + "backend": { + "image": "mmapp-test/backend:ux-auth211", + "imageId": "sha256:904c844a729465e8cdb48278a1f2829c88fe2764941ae60b4a0d05dc2f2d3b18", + "running": true, + "health": "healthy" + }, + "frontend": { + "image": "mmapp-test/frontend:ux-gre210", + "imageId": "sha256:b4b1280f729e89de83b30bd242d37bda831306720b3c78cb9eef6048c3e3178e", + "running": true, + "health": null + } + }, + "rollbackTags": { + "backend": "ux-gre210", + "frontend": "ux-gre210" + }, + "backendSourceMatched": 477, + "compiledMatched": 1048 +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/auth211-live-2026-10-13.json b/docs/ux-ui/acceptance/auth211-live-2026-10-13.json new file mode 100644 index 00000000..4d607da3 --- /dev/null +++ b/docs/ux-ui/acceptance/auth211-live-2026-10-13.json @@ -0,0 +1,193 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "backend": "ux-auth211", + "frontend": "ux-gre210", + "cases": [ + { + "role": "anonymous", + "path": "/api/servers", + "method": "GET", + "status": 401 + }, + { + "role": "anonymous", + "path": "/api/servers", + "method": "HEAD", + "status": 401 + }, + { + "role": "anonymous", + "path": "/api/%73ervers", + "method": "GET", + "status": 401 + }, + { + "role": "anonymous", + "path": "/api/%73ervers", + "method": "HEAD", + "status": 401 + }, + { + "role": "anonymous", + "path": "/%61pi/servers", + "method": "GET", + "status": 401 + }, + { + "role": "anonymous", + "path": "/%61pi/servers", + "method": "HEAD", + "status": 401 + }, + { + "role": "anonymous", + "path": "/%61%70%69/servers", + "method": "GET", + "status": 401 + }, + { + "role": "anonymous", + "path": "/%61%70%69/servers", + "method": "HEAD", + "status": 401 + }, + { + "role": "dashboard", + "path": "/api/servers", + "method": "GET", + "status": 403, + "privateMaterialAbsent": true + }, + { + "role": "dashboard", + "path": "/api/%73ervers", + "method": "GET", + "status": 403, + "privateMaterialAbsent": true + }, + { + "role": "dashboard", + "path": "/%61pi/servers", + "method": "GET", + "status": 403, + "privateMaterialAbsent": true + }, + { + "role": "dashboard", + "path": "/api/gre/tunnels", + "method": "GET", + "status": 403, + "pskAbsent": true + }, + { + "role": "dashboard", + "path": "/api/gre/tunnels", + "method": "PATCH", + "status": 403, + "emptyBody": true, + "nativeApplication": false + }, + { + "role": "dashboard", + "path": "/api/%67re/tunnels", + "method": "GET", + "status": 403, + "pskAbsent": true + }, + { + "role": "dashboard", + "path": "/api/%67re/tunnels", + "method": "PATCH", + "status": 403, + "emptyBody": true, + "nativeApplication": false + }, + { + "role": "dashboard", + "path": "/%61pi/gre/tunnels", + "method": "GET", + "status": 403, + "pskAbsent": true + }, + { + "role": "dashboard", + "path": "/%61pi/gre/tunnels", + "method": "PATCH", + "status": 403, + "emptyBody": true, + "nativeApplication": false + }, + { + "role": "reader", + "path": "/api/servers", + "method": "GET", + "status": 200, + "privateMaterialAbsent": true + }, + { + "role": "reader", + "path": "/api/%73ervers", + "method": "GET", + "status": 200, + "privateMaterialAbsent": true + }, + { + "role": "reader", + "path": "/%61pi/servers", + "method": "GET", + "status": 200, + "privateMaterialAbsent": true + }, + { + "role": "reader", + "path": "/api/gre/tunnels", + "method": "GET", + "status": 200, + "pskAbsent": true + }, + { + "role": "reader", + "path": "/api/gre/tunnels", + "method": "PATCH", + "status": 403, + "emptyBody": true, + "nativeApplication": false + }, + { + "role": "reader", + "path": "/api/%67re/tunnels", + "method": "GET", + "status": 200, + "pskAbsent": true + }, + { + "role": "reader", + "path": "/api/%67re/tunnels", + "method": "PATCH", + "status": 403, + "emptyBody": true, + "nativeApplication": false + }, + { + "role": "reader", + "path": "/%61pi/gre/tunnels", + "method": "GET", + "status": 200, + "pskAbsent": true + }, + { + "role": "reader", + "path": "/%61pi/gre/tunnels", + "method": "PATCH", + "status": 403, + "emptyBody": true, + "nativeApplication": false + } + ], + "publicAuthConfig": 200, + "realPortalJWT": true, + "rawResponseBodiesStored": false, + "ownedUsersRemoved": true, + "scope": "Anonymous GET/HEAD and actual restricted roles; denied PATCH uses empty body and cannot apply native objects" +} diff --git a/docs/ux-ui/acceptance/auth211-production-result.json b/docs/ux-ui/acceptance/auth211-production-result.json new file mode 100644 index 00000000..b8b9b0dc --- /dev/null +++ b/docs/ux-ui/acceptance/auth211-production-result.json @@ -0,0 +1,195 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "database": "mm_accept_166_1791901195054", + "baseline": false, + "cases": [ + { + "path": "/api/servers", + "method": "GET", + "role": "anonymous", + "status": 401 + }, + { + "path": "/api/servers", + "method": "HEAD", + "role": "anonymous", + "status": 401 + }, + { + "path": "/api/%73ervers", + "method": "GET", + "role": "anonymous", + "status": 401 + }, + { + "path": "/api/%73ervers", + "method": "HEAD", + "role": "anonymous", + "status": 401 + }, + { + "path": "/%61pi/servers", + "method": "GET", + "role": "anonymous", + "status": 401 + }, + { + "path": "/%61pi/servers", + "method": "HEAD", + "role": "anonymous", + "status": 401 + }, + { + "path": "/%61%70%69/servers", + "method": "GET", + "role": "anonymous", + "status": 401 + }, + { + "path": "/%61%70%69/servers", + "method": "HEAD", + "role": "anonymous", + "status": 401 + }, + { + "path": "/api/gre/tunnels", + "method": "GET", + "role": "anonymous", + "status": 401 + }, + { + "path": "/api/gre/tunnels", + "method": "HEAD", + "role": "anonymous", + "status": 401 + }, + { + "path": "/%61pi/gre/tunnels", + "method": "GET", + "role": "anonymous", + "status": 401 + }, + { + "path": "/%61pi/gre/tunnels", + "method": "HEAD", + "role": "anonymous", + "status": 401 + }, + { + "path": "/api/gre/tunnels", + "method": "GET", + "role": "dashboard", + "status": 403, + "privateMaterialStored": false + }, + { + "path": "/api/gre/tunnels", + "method": "PATCH", + "role": "dashboard", + "status": 403 + }, + { + "path": "/api/gre/tunnels", + "method": "GET", + "role": "reader", + "status": 200, + "privateMaterialStored": false + }, + { + "path": "/api/gre/tunnels", + "method": "PATCH", + "role": "reader", + "status": 403 + }, + { + "path": "/api/gre/tunnels", + "method": "GET", + "role": "writer", + "status": 200, + "privateMaterialStored": false + }, + { + "path": "/api/%67re/tunnels", + "method": "GET", + "role": "dashboard", + "status": 403, + "privateMaterialStored": false + }, + { + "path": "/api/%67re/tunnels", + "method": "PATCH", + "role": "dashboard", + "status": 403 + }, + { + "path": "/api/%67re/tunnels", + "method": "GET", + "role": "reader", + "status": 200, + "privateMaterialStored": false + }, + { + "path": "/api/%67re/tunnels", + "method": "PATCH", + "role": "reader", + "status": 403 + }, + { + "path": "/api/%67re/tunnels", + "method": "GET", + "role": "writer", + "status": 200, + "privateMaterialStored": false + }, + { + "path": "/%61pi/gre/tunnels", + "method": "GET", + "role": "dashboard", + "status": 403, + "privateMaterialStored": false + }, + { + "path": "/%61pi/gre/tunnels", + "method": "PATCH", + "role": "dashboard", + "status": 403 + }, + { + "path": "/%61pi/gre/tunnels", + "method": "GET", + "role": "reader", + "status": 200, + "privateMaterialStored": false + }, + { + "path": "/%61pi/gre/tunnels", + "method": "PATCH", + "role": "reader", + "status": 403 + }, + { + "path": "/%61pi/gre/tunnels", + "method": "GET", + "role": "writer", + "status": 200, + "privateMaterialStored": false + }, + { + "path": "/api/auth/config", + "role": "anonymous", + "status": 200, + "publicConfig": true + }, + { + "path": "/%61pi/auth/config", + "role": "anonymous", + "status": 200, + "publicConfig": true + } + ], + "scope": "Production compiled canonical auth/RBAC using own restricted PostgreSQL, local native HTTP fixture and synthetic JWT/PSK", + "passed": true, + "nativeWrites": 0, + "databaseAndRoleRemoved": true +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/auth211-profile-2026-10-13.json b/docs/ux-ui/acceptance/auth211-profile-2026-10-13.json new file mode 100644 index 00000000..8ab8d866 --- /dev/null +++ b/docs/ux-ui/acceptance/auth211-profile-2026-10-13.json @@ -0,0 +1,13 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "canonicalAuthCases": 42, + "commands": [ + "npm --prefix backend run test:auth", + "npx tsx backend/src/plugins/auth.geoip.test.ts", + "npx tsx backend/src/plugins/auth.netflow-settings.test.ts" + ], + "passed": true, + "backendBuildPassed": true, + "scope": "Matched static/parameter routes, GET/HEAD/PATCH, OSPF read preview, public auth config/health, existing auth/GeoIP/private NetFlow export policy" +} diff --git a/docs/ux-ui/acceptance/compiled211-result.json b/docs/ux-ui/acceptance/compiled211-result.json new file mode 100644 index 00000000..3c882bf3 --- /dev/null +++ b/docs/ux-ui/acceptance/compiled211-result.json @@ -0,0 +1,1058 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "backendVersion": "1.0.0-test.auth211", + "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-context-reader.js", + "backend/dist/services/alert-engine/collector-context-reader.js.map", + "backend/dist/services/alert-engine/collector-context-reader.d.ts", + "backend/dist/services/alert-engine/collector-context-reader.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/monitoring-history.js", + "backend/dist/services/alert-engine/monitoring-history.js.map", + "backend/dist/services/alert-engine/monitoring-history.d.ts", + "backend/dist/services/alert-engine/monitoring-history.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/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", + "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-read.js", + "backend/dist/services/gre-read.js.map", + "backend/dist/services/gre-read.d.ts", + "backend/dist/services/gre-read.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-collection-lock.js", + "backend/dist/services/traffic-collection-lock.js.map", + "backend/dist/services/traffic-collection-lock.d.ts", + "backend/dist/services/traffic-collection-lock.d.ts.map", + "backend/dist/services/traffic-collection-state.js", + "backend/dist/services/traffic-collection-state.js.map", + "backend/dist/services/traffic-collection-state.d.ts", + "backend/dist/services/traffic-collection-state.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-freshness.js", + "backend/dist/services/traffic-freshness.js.map", + "backend/dist/services/traffic-freshness.d.ts", + "backend/dist/services/traffic-freshness.d.ts.map", + "backend/dist/services/traffic-live.js", + "backend/dist/services/traffic-live.js.map", + "backend/dist/services/traffic-live.d.ts", + "backend/dist/services/traffic-live.d.ts.map", + "backend/dist/services/traffic-observation.js", + "backend/dist/services/traffic-observation.js.map", + "backend/dist/services/traffic-observation.d.ts", + "backend/dist/services/traffic-observation.d.ts.map", + "backend/dist/services/traffic-peer-observation.js", + "backend/dist/services/traffic-peer-observation.js.map", + "backend/dist/services/traffic-peer-observation.d.ts", + "backend/dist/services/traffic-peer-observation.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" + ], + "missing": [], + "different": [] +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/source211-result.json b/docs/ux-ui/acceptance/source211-result.json new file mode 100644 index 00000000..cb1ad26b --- /dev/null +++ b/docs/ux-ui/acceptance/source211-result.json @@ -0,0 +1,10 @@ +{ + "date": "2026-10-13", + "block": "12.5.211", + "kinds": [ + { + "kind": "backend", + "matched": 477 + } + ] +} \ No newline at end of file