From a8b80d9914ad03a08e2095e3957969a0f675458e Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 13 Oct 2026 01:31:02 +0700 Subject: [PATCH] =?UTF-8?q?chore(tests):=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D1=82=D1=8C=20=D0=B0=D1=80=D1=85=D0=B8=D0=B2=D1=8B?= =?UTF-8?q?=20=D1=81=20=D0=B8=D0=B4=D0=B5=D0=BD=D1=82=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=D1=8E=20=D1=81=D1=87=D1=91=D1=82=D1=87?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/traffic-identity-restore.mjs | 35 +++++++++++++++++++ docs/ux-ui-external-acceptance.md | 19 ++++++++-- docs/ux-ui-plan.md | 6 ++-- docs/ux-ui-progress.md | 17 ++++++++- docs/ux-ui-remaining-acceptance.md | 17 ++++++++- docs/ux-ui-stage-12.md | 17 ++++++++- docs/ux-ui-test-server.md | 19 ++++++++-- .../traffic-identity-restore-2026-10-13.json | 32 +++++++++++++++++ 8 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 backend/scripts/acceptance/traffic-identity-restore.mjs create mode 100644 docs/ux-ui/acceptance/traffic-identity-restore-2026-10-13.json diff --git a/backend/scripts/acceptance/traffic-identity-restore.mjs b/backend/scripts/acceptance/traffic-identity-restore.mjs new file mode 100644 index 00000000..f3a604b0 --- /dev/null +++ b/backend/scripts/acceptance/traffic-identity-restore.mjs @@ -0,0 +1,35 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs/promises' +import {execFileSync} from 'node:child_process' +import crypto from 'node:crypto' +import pg from 'pg' +const name=process.env.MMAPP_OWN_SQL_DB,url=process.env.DATABASE_URL,base='/app/backend/acceptance' +assert(/^mm_accept_166_\d+$/.test(name));assert.equal(new URL(url).pathname,'/'+name);assert.equal(new URL(url).username,name) +const report={date:'2026-10-13',block:'12.5.187',database:name,productionDatabaseTouched:false,productionEnvCopied:false,cases:[],scriptSha256:crypto.createHash('sha256').update(await fs.readFile(new URL(import.meta.url))).digest('hex')} +const client=new pg.Client({connectionString:url});await client.connect() +const check=async()=>{assert.equal((await client.query('SELECT current_database() AS n')).rows[0].n,name)} +const init=()=>execFileSync(process.execPath,['--input-type=module','-e',"const {initDatabase}=await import('/app/backend/dist/db/bootstrap.js');const {closePool}=await import('/app/backend/dist/db/index.js');await initDatabase();await closePool();"],{env:{...process.env,DATABASE_PATH:'/tmp/'+name+'/missing.db'},stdio:'pipe'}) +const directory='/tmp/'+name;await fs.mkdir(directory);let passed=false +try{ + await check();const role=(await client.query('SELECT rolsuper,rolcreatedb,rolcreaterole,rolbypassrls FROM pg_roles WHERE rolname=current_user')).rows[0];assert(Object.values(role).every(v=>v===false)) + init();const at=new Date().toISOString(),earlier=new Date(Date.parse(at)-30_000).toISOString(),identity=JSON.stringify([at,'*1']) + const id=(await client.query("INSERT INTO servers(name,host,enabled,username,password,updated_at) VALUES('Own restore187','127.0.0.1',false,'fixture','fixture',$1) RETURNING id",[at])).rows[0].id + await client.query("INSERT INTO traffic_samples(server_id,interface_name,sampled_at,rx_bytes,tx_bytes,flags) VALUES($1,'ether1',$2,0,0,13),($1,'ether1',$3,1024,1024,13)",[id,earlier,at]) + // An archive with the exact pre-0012 column/marker shape, constructed only in this owned database. + await check();await client.query('ALTER TABLE traffic_samples DROP COLUMN native_counter_identity');await client.query("DELETE FROM schema_migrations WHERE id='0012_traffic_counter_identity'") + const old=directory+'/legacy.dump',native=directory+'/native.dump' + const dump=file=>execFileSync('pg_dump',['--format=custom','--no-owner','--no-acl','--file',file,'--dbname',url],{stdio:'pipe'}) + dump(old);init();await client.query("UPDATE traffic_samples SET native_counter_identity='mutated' WHERE server_id=$1",[id]) + const {restorePartitionedDatabase}=await import('/app/backend/dist/services/system-database-partition-restore.js') + const restore=async file=>{await check();await restorePartitionedDatabase(file,url,{prepareSql:async p=>{assert(p.startsWith(directory+'/'));await fs.writeFile(p,'',{flag:'wx',mode:0o600})},command:async(cmd,args)=>{assert(['pg_restore','psql'].includes(cmd));if(cmd==='psql')assert.equal(args[args.indexOf('-d')+1],url);return execFileSync(cmd,args,{stdio:'pipe'})}})} + await restore(old);assert.equal((await client.query("SELECT count(*)::int AS n FROM information_schema.columns WHERE table_schema='public' AND table_name='traffic_samples' AND column_name='native_counter_identity'")).rows[0].n,0);report.cases.push({case:'legacy archive restores original schema',passed:true}) + init();let rows=(await client.query('SELECT native_counter_identity,flags,rx_bytes FROM traffic_samples WHERE server_id=$1 ORDER BY sampled_at',[id])).rows + assert.equal(rows.length,2);assert(rows.every(r=>r.native_counter_identity===null&&r.flags===13));assert.deepEqual(rows.map(r=>Number(r.rx_bytes)),[0,1024]);report.cases.push({case:'bootstrap migrates legacy archive without guessed identities or flag rewrite',passed:true}) + await client.query('UPDATE traffic_samples SET native_counter_identity=$1,flags=CASE WHEN rx_bytes=0 THEN 45 ELSE 61 END WHERE server_id=$2',[identity,id]);dump(native) + await client.query('DELETE FROM traffic_samples WHERE server_id=$1',[id]);assert.equal((await client.query('SELECT count(*)::int AS n FROM traffic_samples WHERE server_id=$1',[id])).rows[0].n,0) + await restore(native);rows=(await client.query('SELECT native_counter_identity,flags,rx_bytes FROM traffic_samples WHERE server_id=$1 ORDER BY sampled_at',[id])).rows + assert.deepEqual(rows.map(r=>r.flags),[45,61]);assert(rows.every(r=>r.native_counter_identity===identity));assert.deepEqual(rows.map(r=>Number(r.rx_bytes)),[0,1024]);report.cases.push({case:'native archive preserves identities, continuity markers and counters',passed:true}) + assert.equal((await client.query("SELECT count(*)::int AS n FROM schema_migrations WHERE id='0012_traffic_counter_identity'")).rows[0].n,1) + report.cases.push({case:'partitioned archive restore and current migration remain valid',passed:true});report.clientVersion=execFileSync('pg_dump',['--version'],{encoding:'utf8'}).trim();report.serverVersion=(await client.query('SHOW server_version')).rows[0].server_version;passed=true +}catch(e){report.errorName=e.name;process.exitCode=1} +finally{await client.end();report.passed=passed;await fs.writeFile(base+'/restore187-result.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report))} diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index eee566c5..63c05b0e 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: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. IPsec78: реальный PSK responder established, mode-config198.18.78.10 и online=true подтверждены API; точные собственные объекты удалены. Сертификатный/DN online, late failure и history restore остаются открытыми. [Отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json), [журнал](ux-ui-progress.md). @@ -696,7 +696,7 @@ flowchart LR ## 12.5.77 — основной блок IPsec (2026-10-09) -Актуальное продолжение 2026-10-13: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). @@ -2224,3 +2224,18 @@ Unit identity/config/legacy-marker/pair guards, backend/application TypeScript [Native GET](ux-ui/acceptance/traffic-identity-native-2026-10-13.json): оба CHR доступны, interface native IDs/flags/counters валидны;0012 applied. Peers фактически0 — positive peer replacement доказан изолированным fixture, не реальным VPN-туннелем. DB read-only/RouterOS config writes0/password changes0/messages0. [Initial API](ux-ui/acceptance/traffic-identity-api-2026-10-13.json) ожидаемо unknown при первом baseline после нового writer; [штатное восстановление](ux-ui/acceptance/traffic-identity-recovery-2026-10-13.json) подтвердило current/rxKnown/txKnown обоих CHR с30s interval без manual collector invocation. [Production UI1440/320](ux-ui/acceptance/traffic-identity-deployed-2026-10-13.json) actual live/receipt labels/no errors/overflow. Native SSE не изменён; предшествующие6E2E185 UI guard checks не пересчитываются как новые186. Следующий187 — own-schema archive restore для nullable native counter identity/continuity flags и старого schema archive с повторным bootstrap migration. Потом отдельная приёмка многопроцессной координации/масштаба/внешних доступов.12.5 открыта. Локальный коммит без push. + +## 12.5.187 — совместимость архивов после миграции counter identity (2026-10-13) + +[Воспроизводимый runner](../backend/scripts/acceptance/traffic-identity-restore.mjs) проверяет namespace/role/current_database до операций; допускает только отдельную mm_accept_166_* базу с ограниченной ролью. Реальные pg_dump/pg_restore/psql18.6 работают с ней через restorePartitionedDatabase из production ux-identity186: archive decode → known-parent preparation → one transactional psql. Production database/env не копируются и не восстанавливаются. Архивы/SQL остаются внутри временного контейнера, только публичный JSON сохранён в Git. + +[4 принятых случая](ux-ui/acceptance/traffic-identity-restore-2026-10-13.json): старый schema archive возвращает отсутствие native_counter_identity; последующий bootstrap добавляет0012 с NULL identities и прежними flags13/counters0,1024 без догадки; новый archive возвращает identity и markers45/61/counters0,1024 после удаления собственных rows; partitioned parent/child restore и migration record0012 остаются корректными. Старый archive fixture сформирован исключительно в собственной базе удалением новой nullable колонки и0012 record: это совместимый pre-0012 shape, не реальный пользовательский backup. Positive native fields — контролируемые fixtures, не counter proof устройства. + +| Архив | Схема результата | +| --- | --- | +| Pre-0012 fixture | old schema/data → restore → bootstrap0012 → identityNULL, flags unchanged | +| Native identity fixture | dump → собственные rows удалены → actual restore → exact identity/flags/counters | + +PostgreSQL server/client18.6, Node22 from production image; отдельный test-client image на официальном postgres:18 собран с проверкой Node/pg_dump. Docker socket в контейнер не передавался. Script SHA256 совпал с локальными байтами. ESLint passed. OwnDB mm_accept_166_1791829512285/role/container удалены, независимая проверка catalog/container absence passed. Рабочие3 контейнера и их runtime186/183 не менялись, реальных серверных/network writes/messages0; отдельная приёмка PostgreSQL restore в полном API/RBAC/multi-writer сценарии этим коротким тестом не заявляется. + +Следующий188 — временный состав измерений: текущая реализация сравнивает количество известной wave с количеством всех series за период. Проверить rename/delete/add interfaces и active sessions, чтобы старый ряд не делал текущий срез навсегда unknown, а новое измерение без baseline не превращалось в measured0. Историю сохранить; причины absent object/optional peer failures и multi-instance остаются явными ограничениями.12.5 открыта. Локальный коммит без push. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index e867d058..f296c897 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-13: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-12. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-12 -Актуальное продолжение 2026-10-13: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. Этапы0–11 завершены в локальных границах журнала. История выполненных внешних блоков и доказательства сохранены в [журнале](ux-ui-stage-12.md) и [протоколе](ux-ui-external-acceptance.md). Реальная Telegram доставка, Portal SSO, multi-instance и оставшиеся профильные сетевые ограничения открыты. @@ -371,6 +371,6 @@ flowchart LR ## 12.5.77 — основной блок IPsec (2026-10-09) -Актуальное продолжение 2026-10-13: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 20a2eb32..6228f2d4 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-13: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -38,6 +38,21 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–168 и ограничения ниже. Runtime backend ux-month149/frontend ux-sessions150. | +## 12.5.187 — совместимость архивов после миграции counter identity (2026-10-13) + +[Воспроизводимый runner](../backend/scripts/acceptance/traffic-identity-restore.mjs) проверяет namespace/role/current_database до операций; допускает только отдельную mm_accept_166_* базу с ограниченной ролью. Реальные pg_dump/pg_restore/psql18.6 работают с ней через restorePartitionedDatabase из production ux-identity186: archive decode → known-parent preparation → one transactional psql. Production database/env не копируются и не восстанавливаются. Архивы/SQL остаются внутри временного контейнера, только публичный JSON сохранён в Git. + +[4 принятых случая](ux-ui/acceptance/traffic-identity-restore-2026-10-13.json): старый schema archive возвращает отсутствие native_counter_identity; последующий bootstrap добавляет0012 с NULL identities и прежними flags13/counters0,1024 без догадки; новый archive возвращает identity и markers45/61/counters0,1024 после удаления собственных rows; partitioned parent/child restore и migration record0012 остаются корректными. Старый archive fixture сформирован исключительно в собственной базе удалением новой nullable колонки и0012 record: это совместимый pre-0012 shape, не реальный пользовательский backup. Positive native fields — контролируемые fixtures, не counter proof устройства. + +| Архив | Схема результата | +| --- | --- | +| Pre-0012 fixture | old schema/data → restore → bootstrap0012 → identityNULL, flags unchanged | +| Native identity fixture | dump → собственные rows удалены → actual restore → exact identity/flags/counters | + +PostgreSQL server/client18.6, Node22 from production image; отдельный test-client image на официальном postgres:18 собран с проверкой Node/pg_dump. Docker socket в контейнер не передавался. Script SHA256 совпал с локальными байтами. ESLint passed. OwnDB mm_accept_166_1791829512285/role/container удалены, независимая проверка catalog/container absence passed. Рабочие3 контейнера и их runtime186/183 не менялись, реальных серверных/network writes/messages0; отдельная приёмка PostgreSQL restore в полном API/RBAC/multi-writer сценарии этим коротким тестом не заявляется. + +Следующий188 — временный состав измерений: текущая реализация сравнивает количество известной wave с количеством всех series за период. Проверить rename/delete/add interfaces и active sessions, чтобы старый ряд не делал текущий срез навсегда unknown, а новое измерение без baseline не превращалось в measured0. Историю сохранить; причины absent object/optional peer failures и multi-instance остаются явными ограничениями.12.5 открыта. Локальный коммит без push. + ## 12.5.186 — подтверждение идентичности пары счётчиков (2026-10-13) Имя интерфейса больше не является единственным основанием новой counter pair. Nullable native_counter_identity хранит нормализованные source.updatedAt и native RouterOS.id (*HEX). Producer подтверждает continuity только когда identity непустая и совпадает с предыдущей строкой того же interface/peer key. Новый native ID, конфигурация источника или missing/invalid ID дают первую pair unknown; следующий подтверждённый poll восстанавливает измерение. Для WG используются peer.id и существующий public-key/iface series key, не ID самого интерфейса. diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index ea58b0b1..15eebe32 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,6 +1,6 @@ # Оставшаяся внешняя приёмка — 2026-10-12 -Это актуальная матрица после 12.5.186. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.187. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-identity186`, frontend `ux-warning183`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. @@ -1139,3 +1139,18 @@ Unit identity/config/legacy-marker/pair guards, backend/application TypeScript [Native GET](ux-ui/acceptance/traffic-identity-native-2026-10-13.json): оба CHR доступны, interface native IDs/flags/counters валидны;0012 applied. Peers фактически0 — positive peer replacement доказан изолированным fixture, не реальным VPN-туннелем. DB read-only/RouterOS config writes0/password changes0/messages0. [Initial API](ux-ui/acceptance/traffic-identity-api-2026-10-13.json) ожидаемо unknown при первом baseline после нового writer; [штатное восстановление](ux-ui/acceptance/traffic-identity-recovery-2026-10-13.json) подтвердило current/rxKnown/txKnown обоих CHR с30s interval без manual collector invocation. [Production UI1440/320](ux-ui/acceptance/traffic-identity-deployed-2026-10-13.json) actual live/receipt labels/no errors/overflow. Native SSE не изменён; предшествующие6E2E185 UI guard checks не пересчитываются как новые186. Следующий187 — own-schema archive restore для nullable native counter identity/continuity flags и старого schema archive с повторным bootstrap migration. Потом отдельная приёмка многопроцессной координации/масштаба/внешних доступов.12.5 открыта. Локальный коммит без push. + +## 12.5.187 — совместимость архивов после миграции counter identity (2026-10-13) + +[Воспроизводимый runner](../backend/scripts/acceptance/traffic-identity-restore.mjs) проверяет namespace/role/current_database до операций; допускает только отдельную mm_accept_166_* базу с ограниченной ролью. Реальные pg_dump/pg_restore/psql18.6 работают с ней через restorePartitionedDatabase из production ux-identity186: archive decode → known-parent preparation → one transactional psql. Production database/env не копируются и не восстанавливаются. Архивы/SQL остаются внутри временного контейнера, только публичный JSON сохранён в Git. + +[4 принятых случая](ux-ui/acceptance/traffic-identity-restore-2026-10-13.json): старый schema archive возвращает отсутствие native_counter_identity; последующий bootstrap добавляет0012 с NULL identities и прежними flags13/counters0,1024 без догадки; новый archive возвращает identity и markers45/61/counters0,1024 после удаления собственных rows; partitioned parent/child restore и migration record0012 остаются корректными. Старый archive fixture сформирован исключительно в собственной базе удалением новой nullable колонки и0012 record: это совместимый pre-0012 shape, не реальный пользовательский backup. Positive native fields — контролируемые fixtures, не counter proof устройства. + +| Архив | Схема результата | +| --- | --- | +| Pre-0012 fixture | old schema/data → restore → bootstrap0012 → identityNULL, flags unchanged | +| Native identity fixture | dump → собственные rows удалены → actual restore → exact identity/flags/counters | + +PostgreSQL server/client18.6, Node22 from production image; отдельный test-client image на официальном postgres:18 собран с проверкой Node/pg_dump. Docker socket в контейнер не передавался. Script SHA256 совпал с локальными байтами. ESLint passed. OwnDB mm_accept_166_1791829512285/role/container удалены, независимая проверка catalog/container absence passed. Рабочие3 контейнера и их runtime186/183 не менялись, реальных серверных/network writes/messages0; отдельная приёмка PostgreSQL restore в полном API/RBAC/multi-writer сценарии этим коротким тестом не заявляется. + +Следующий188 — временный состав измерений: текущая реализация сравнивает количество известной wave с количеством всех series за период. Проверить rename/delete/add interfaces и active sessions, чтобы старый ряд не делал текущий срез навсегда unknown, а новое измерение без baseline не превращалось в measured0. Историю сохранить; причины absent object/optional peer failures и multi-instance остаются явными ограничениями.12.5 открыта. Локальный коммит без push. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 4ba10205..0dc2c7f6 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: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -3529,3 +3529,18 @@ Unit identity/config/legacy-marker/pair guards, backend/application TypeScript [Native GET](ux-ui/acceptance/traffic-identity-native-2026-10-13.json): оба CHR доступны, interface native IDs/flags/counters валидны;0012 applied. Peers фактически0 — positive peer replacement доказан изолированным fixture, не реальным VPN-туннелем. DB read-only/RouterOS config writes0/password changes0/messages0. [Initial API](ux-ui/acceptance/traffic-identity-api-2026-10-13.json) ожидаемо unknown при первом baseline после нового writer; [штатное восстановление](ux-ui/acceptance/traffic-identity-recovery-2026-10-13.json) подтвердило current/rxKnown/txKnown обоих CHR с30s interval без manual collector invocation. [Production UI1440/320](ux-ui/acceptance/traffic-identity-deployed-2026-10-13.json) actual live/receipt labels/no errors/overflow. Native SSE не изменён; предшествующие6E2E185 UI guard checks не пересчитываются как новые186. Следующий187 — own-schema archive restore для nullable native counter identity/continuity flags и старого schema archive с повторным bootstrap migration. Потом отдельная приёмка многопроцессной координации/масштаба/внешних доступов.12.5 открыта. Локальный коммит без push. + +## 12.5.187 — совместимость архивов после миграции counter identity (2026-10-13) + +[Воспроизводимый runner](../backend/scripts/acceptance/traffic-identity-restore.mjs) проверяет namespace/role/current_database до операций; допускает только отдельную mm_accept_166_* базу с ограниченной ролью. Реальные pg_dump/pg_restore/psql18.6 работают с ней через restorePartitionedDatabase из production ux-identity186: archive decode → known-parent preparation → one transactional psql. Production database/env не копируются и не восстанавливаются. Архивы/SQL остаются внутри временного контейнера, только публичный JSON сохранён в Git. + +[4 принятых случая](ux-ui/acceptance/traffic-identity-restore-2026-10-13.json): старый schema archive возвращает отсутствие native_counter_identity; последующий bootstrap добавляет0012 с NULL identities и прежними flags13/counters0,1024 без догадки; новый archive возвращает identity и markers45/61/counters0,1024 после удаления собственных rows; partitioned parent/child restore и migration record0012 остаются корректными. Старый archive fixture сформирован исключительно в собственной базе удалением новой nullable колонки и0012 record: это совместимый pre-0012 shape, не реальный пользовательский backup. Positive native fields — контролируемые fixtures, не counter proof устройства. + +| Архив | Схема результата | +| --- | --- | +| Pre-0012 fixture | old schema/data → restore → bootstrap0012 → identityNULL, flags unchanged | +| Native identity fixture | dump → собственные rows удалены → actual restore → exact identity/flags/counters | + +PostgreSQL server/client18.6, Node22 from production image; отдельный test-client image на официальном postgres:18 собран с проверкой Node/pg_dump. Docker socket в контейнер не передавался. Script SHA256 совпал с локальными байтами. ESLint passed. OwnDB mm_accept_166_1791829512285/role/container удалены, независимая проверка catalog/container absence passed. Рабочие3 контейнера и их runtime186/183 не менялись, реальных серверных/network writes/messages0; отдельная приёмка PostgreSQL restore в полном API/RBAC/multi-writer сценарии этим коротким тестом не заявляется. + +Следующий188 — временный состав измерений: текущая реализация сравнивает количество известной wave с количеством всех series за период. Проверить rename/delete/add interfaces и active sessions, чтобы старый ряд не делал текущий срез навсегда unknown, а новое измерение без baseline не превращалось в measured0. Историю сохранить; причины absent object/optional peer failures и multi-instance остаются явными ограничениями.12.5 открыта. Локальный коммит без push. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 057f80f5..1fd7d841 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: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. | Параметр | Проверенное состояние | | --- | --- | @@ -708,7 +708,7 @@ flowchart LR ## 12.5.77 — основной блок IPsec (2026-10-09) -Актуальное продолжение 2026-10-13: завершён12.5.186 — native counter identity+source config, declared continuity flags, migration0012 без переписывания legacy. OwnSQL62/37613ms/types/build/source458+524/1040compiled/native2/recovery2/browser2 passed. Backend ux-identity186 healthy/frontend ux-warning183; ownDB/role/container удалены. Следующий187 — совместимость backup/restore после nullable-column migration;12.5 открыта. +Актуальное продолжение 2026-10-13: завершён12.5.187 — actual PG18.6 archive restore: legacy schema→0012 bootstrap без guessed identity/flags; native identity/continuity/counters preserved.4cases/real pg_dump+restore helper passed, ownDB/role/container removed; production DB/runtime untouched (backend ux-identity186/frontend ux-warning183). Следующий188 — history wave membership после rename/delete/add interfaces;12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). @@ -1955,3 +1955,18 @@ Unit identity/config/legacy-marker/pair guards, backend/application TypeScript [Native GET](ux-ui/acceptance/traffic-identity-native-2026-10-13.json): оба CHR доступны, interface native IDs/flags/counters валидны;0012 applied. Peers фактически0 — positive peer replacement доказан изолированным fixture, не реальным VPN-туннелем. DB read-only/RouterOS config writes0/password changes0/messages0. [Initial API](ux-ui/acceptance/traffic-identity-api-2026-10-13.json) ожидаемо unknown при первом baseline после нового writer; [штатное восстановление](ux-ui/acceptance/traffic-identity-recovery-2026-10-13.json) подтвердило current/rxKnown/txKnown обоих CHR с30s interval без manual collector invocation. [Production UI1440/320](ux-ui/acceptance/traffic-identity-deployed-2026-10-13.json) actual live/receipt labels/no errors/overflow. Native SSE не изменён; предшествующие6E2E185 UI guard checks не пересчитываются как новые186. Следующий187 — own-schema archive restore для nullable native counter identity/continuity flags и старого schema archive с повторным bootstrap migration. Потом отдельная приёмка многопроцессной координации/масштаба/внешних доступов.12.5 открыта. Локальный коммит без push. + +## 12.5.187 — совместимость архивов после миграции counter identity (2026-10-13) + +[Воспроизводимый runner](../backend/scripts/acceptance/traffic-identity-restore.mjs) проверяет namespace/role/current_database до операций; допускает только отдельную mm_accept_166_* базу с ограниченной ролью. Реальные pg_dump/pg_restore/psql18.6 работают с ней через restorePartitionedDatabase из production ux-identity186: archive decode → known-parent preparation → one transactional psql. Production database/env не копируются и не восстанавливаются. Архивы/SQL остаются внутри временного контейнера, только публичный JSON сохранён в Git. + +[4 принятых случая](ux-ui/acceptance/traffic-identity-restore-2026-10-13.json): старый schema archive возвращает отсутствие native_counter_identity; последующий bootstrap добавляет0012 с NULL identities и прежними flags13/counters0,1024 без догадки; новый archive возвращает identity и markers45/61/counters0,1024 после удаления собственных rows; partitioned parent/child restore и migration record0012 остаются корректными. Старый archive fixture сформирован исключительно в собственной базе удалением новой nullable колонки и0012 record: это совместимый pre-0012 shape, не реальный пользовательский backup. Positive native fields — контролируемые fixtures, не counter proof устройства. + +| Архив | Схема результата | +| --- | --- | +| Pre-0012 fixture | old schema/data → restore → bootstrap0012 → identityNULL, flags unchanged | +| Native identity fixture | dump → собственные rows удалены → actual restore → exact identity/flags/counters | + +PostgreSQL server/client18.6, Node22 from production image; отдельный test-client image на официальном postgres:18 собран с проверкой Node/pg_dump. Docker socket в контейнер не передавался. Script SHA256 совпал с локальными байтами. ESLint passed. OwnDB mm_accept_166_1791829512285/role/container удалены, независимая проверка catalog/container absence passed. Рабочие3 контейнера и их runtime186/183 не менялись, реальных серверных/network writes/messages0; отдельная приёмка PostgreSQL restore в полном API/RBAC/multi-writer сценарии этим коротким тестом не заявляется. + +Следующий188 — временный состав измерений: текущая реализация сравнивает количество известной wave с количеством всех series за период. Проверить rename/delete/add interfaces и active sessions, чтобы старый ряд не делал текущий срез навсегда unknown, а новое измерение без baseline не превращалось в measured0. Историю сохранить; причины absent object/optional peer failures и multi-instance остаются явными ограничениями.12.5 открыта. Локальный коммит без push. diff --git a/docs/ux-ui/acceptance/traffic-identity-restore-2026-10-13.json b/docs/ux-ui/acceptance/traffic-identity-restore-2026-10-13.json new file mode 100644 index 00000000..e6ada096 --- /dev/null +++ b/docs/ux-ui/acceptance/traffic-identity-restore-2026-10-13.json @@ -0,0 +1,32 @@ +{ + "date": "2026-10-13", + "block": "12.5.187", + "database": "mm_accept_166_1791829512285", + "productionDatabaseTouched": false, + "productionEnvCopied": false, + "cases": [ + { + "case": "legacy archive restores original schema", + "passed": true + }, + { + "case": "bootstrap migrates legacy archive without guessed identities or flag rewrite", + "passed": true + }, + { + "case": "native archive preserves identities, continuity markers and counters", + "passed": true + }, + { + "case": "partitioned archive restore and current migration remain valid", + "passed": true + } + ], + "scriptSha256": "40a79ba36d1a33fb3c5f9862cc2daa33932deefb02d4301ceafa7f96c3adce3d", + "clientVersion": "pg_dump (PostgreSQL) 18.6 (Debian 18.6-1.pgdg13+2)", + "serverVersion": "18.6", + "passed": true, + "databaseRemoved": true, + "roleRemoved": true, + "testContainerRemoved": true +} \ No newline at end of file