diff --git a/backend/scripts/acceptance/telegram-outbox-live.mjs b/backend/scripts/acceptance/telegram-outbox-live.mjs index 83c28706..3cc07513 100644 --- a/backend/scripts/acceptance/telegram-outbox-live.mjs +++ b/backend/scripts/acceptance/telegram-outbox-live.mjs @@ -3,6 +3,8 @@ import fs from 'node:fs' import {spawn} from 'node:child_process' // Never part of test:all: full mode sends three messages; resume mode sends one intentional duplicate. +const label=process.env.MMAPP_LIVE_TELEGRAM_TEST_LABEL??'197' +assert(/^\d{3}$/.test(label)) const resume=process.env.MMAPP_LIVE_TELEGRAM_RESUME==='manual-retry-only' const database=process.env.MMAPP_OWN_SQL_DB assert(/^mm_accept_166_\d+$/.test(database??''),'An explicitly owned test database is required') @@ -23,16 +25,16 @@ const {enqueueTelegramOutbox,dispatchPendingOutbox,getAlertsOutboxOverview}=awai assert.equal((await pool.query('SELECT current_database() AS name')).rows[0].name,database) const permissions=(await pool.query('SELECT rolsuper,rolcreatedb,rolcreaterole,rolbypassrls FROM pg_roles WHERE rolname=current_user')).rows[0] assert(Object.values(permissions).every(v=>v===false)) -const root='/app/backend/acceptance',prefix='own-live197-'+Date.now(),ownedUsers=[],cases=[] -const report={date:'2026-10-13',block:'12.5.197',database,resumeOnly:resume,scope:'Production compiled outbox, owned PostgreSQL, actual Portal JWT and real Telegram provider',cases,providerSendCalls:0,providerAcceptanceIds:[],ownPortalUsersRemoved:false,passed:false} +const root='/app/backend/acceptance',prefix='own-live'+label+'-'+Date.now(),ownedUsers=[],cases=[] +const report={date:'2026-10-13',block:'12.5.'+label,database,resumeOnly:resume,scope:'Production compiled outbox, owned PostgreSQL, actual Portal JWT and real Telegram provider',cases,providerSendCalls:0,requestTrace:[],providerAcceptanceIds:[],ownPortalUsersRemoved:false,passed:false} let app,adminToken,originalFetch=globalThis.fetch const portalUrl='http://portal:8080' async function portalCall(path,method='GET',body,token){ const r=await originalFetch(portalUrl+path,{method,headers:{...(body!==undefined?{'content-type':'application/json'}:{}),...(token?{Authorization:'Bearer '+token}:{})},body:body===undefined?undefined:JSON.stringify(body)}) const text=await r.text();return {status:r.status,data:text?JSON.parse(text):null} } -const payload=(number)=>({text:`TEST197 №${number} — очередь Telegram. ${number===1?'Проверка dedupe и двух отправителей.':'Проверка unknown и намеренного ручного повтора.'}`,chatId:bot.chatId, - history:{id:prefix+'-history'+number,ruleId:null,groupId:null,ruleName:'Own TEST197 №'+number,severity:'info',message:'Контролируемая приёмка очереди Telegram',firedAt:new Date().toISOString()}}) +const payload=(number)=>({text:`TEST${label} №${number} — очередь Telegram. ${number===1?'Проверка dedupe и двух отправителей.':'Проверка unknown и намеренного ручного повтора.'}`,chatId:bot.chatId, + history:{id:prefix+'-history'+number,ruleId:null,groupId:null,ruleName:'Own TEST'+label+' №'+number,severity:'info',message:'Контролируемая приёмка очереди Telegram',firedAt:new Date().toISOString()}}) async function sender(){ const code=`import assert from 'node:assert/strict';import {pool,closePool} from '/app/backend/dist/db/index.js';import {dispatchPendingOutbox} from '/app/backend/dist/services/alert-engine/outbox.js';assert.equal((await pool.query('SELECT current_database() AS name')).rows[0].name,process.env.MMAPP_OWN_SQL_DB);let calls=0,ids=[];const native=globalThis.fetch;globalThis.fetch=async(...args)=>{const r=await native(...args);if(new URL(String(args[0])).pathname.endsWith('/sendMessage')){calls++;const d=await r.clone().json();if(d.ok)ids.push(d.result.message_id)}return r};try{const result=await dispatchPendingOutbox(1);console.log(JSON.stringify({result,calls,ids}))}finally{await closePool()}` return new Promise((resolve,reject)=>{ @@ -47,7 +49,7 @@ try{ await updateTelegramSettings({token:bot.token,chatId:bot.chatId,messageThreadId:null}) const login=await portalCall('/api/v1/auth/login','POST',{email:portal.email,password:portal.password});assert.equal(login.status,200);adminToken=login.data.access_token const readerEmail=prefix+'@mmapp.test' - const created=await portalCall('/api/v1/admin/users','POST',{email:readerEmail,password:portal.password,name:'Own TEST197 reader',apps:['mm'],permissions:['mm:alerts:read']},adminToken) + const created=await portalCall('/api/v1/admin/users','POST',{email:readerEmail,password:portal.password,name:'Own TEST'+label+' reader',apps:['mm'],permissions:['mm:alerts:read']},adminToken) assert.equal(created.status,201);ownedUsers.push(created.data.id) fs.writeFileSync(root+'/owned-portal-users-private.json',JSON.stringify(ownedUsers),{mode:0o600}) const readerLogin=await portalCall('/api/v1/auth/login','POST',{email:readerEmail,password:portal.password});assert.equal(readerLogin.status,200) @@ -63,15 +65,21 @@ try{ assert.equal(Number((await pool.query('SELECT count(*) AS n FROM alert_history WHERE id=$1 AND sent_ok=true',[prefix+'-history1'])).rows[0].n),1) cases.push({name:'dedupe and independent senders',senders:2,queuedRows:1,providerSends:1,sentHistoryRows:1}) } + let lastSendAt=Date.now() globalThis.fetch=async(...args)=>{ const sending=new URL(String(args[0])).pathname.endsWith('/sendMessage') - if(sending){assert(report.providerSendCalls<(resume?1:3),'Live send budget exhausted');report.providerSendCalls++} - const response=await originalFetch(...args) + if(sending){await new Promise(resolve=>setTimeout(resolve,Math.max(0,1500-(Date.now()-lastSendAt))));lastSendAt=Date.now();assert(report.providerSendCalls<(resume?1:3),'Live send budget exhausted');report.providerSendCalls++} + const trace=sending?{requestNumber:report.providerSendCalls,startedAt:new Date().toISOString()}:null + if(trace)report.requestTrace.push(trace) + let response + try{response=await originalFetch(...args)}catch(e){if(trace)trace.fetchFailed=true;throw e} if(sending){ - const accepted=await response.clone().json() + trace.httpStatus=response.status + const accepted=await response.clone().json().catch(()=>({ok:false})) + trace.providerAccepted=accepted.ok===true if(accepted.ok!==true){report.providerRejectionCodes??=[];report.providerRejectionCodes.push(accepted.error_code??null);return response} report.providerAcceptanceIds.push(accepted.result.message_id) - if(suppressReceipt){suppressReceipt=false;throw Error('Own TEST197 receipt suppressed after confirmed provider acceptance')} + if(suppressReceipt){trace.receiptSuppressed=true;suppressReceipt=false;throw Error('Own TEST197 receipt suppressed after confirmed provider acceptance')} } return response } diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 5081f797..e886c42e 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: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.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: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). @@ -2446,3 +2446,13 @@ Production compiled ux-lock200 на own DB: SIGKILL recovery passed; lock connec Протоколы: [baseline](ux-ui/acceptance/lifecycle200-baseline-result.json), [fixed lifecycle](ux-ui/acceptance/lifecycle200-fixed-result.json), [SQL profile](ux-ui/acceptance/owned200-result.json), [compiled](ux-ui/acceptance/compiled200-result.json), [deployment/bounds](ux-ui/acceptance/lock200-deployment-2026-10-13.json), [live traffic](ux-ui/acceptance/traffic-lock200-deployed-2026-10-13.json). Следующий201: цельный Telegram live197 с диагностикой начала requests/response codes/dispatch outcome/status и ограничением3 сообщений в собственном чате. Controlled lost receipt остаётся имитацией; первоначальный failed evidence не удалять.12.5 открыта. + +## 12.5.201 — цельный живой сценарий очереди Telegram (2026-10-13) + +Обновлён acceptance driver: ограниченный TEST label, request-start counters, safe HTTP status/accepted trace, dispatch outcome и финальная строка очереди; Telegram send pacing1500ms, отрицательные ответы provider не искажаются assertion в unknown. Драйвер не входит вtest:all, явный own DB/chat/duplicate-risk ACK обязательны, число live sends ограничено3 (resume1). Изменение только приёмочного инструмента; продуктовая очередь не менялась. + +Actual production compiled backend ux-lock200, ограниченная PostgreSQL own роль и real Portal JWT. В одном непрерывном прогоне/одной БД: duplicate dedupeKey → одна запись; два независимых sender процесса → один provider send и одна sent/history. Telegram accepted№2, receipt intentionally suppressed → unknown; повторная автоматическая диспетчеризация не отправляет. Reader retry403, missing acknowledgement400, admin version0→1 pending200, stale retry409. После подтверждённого ручного retry Telegram accepted, sent1/failed0/held0, итог две sent строки/две history. Provider принял три сообщения TEST201(IDs6/7/8); пользователь подтвердил одно№1 и два№2. + +Own DB/role/container и Portal reader user удалены, отдельный private bot file удалён; рабочие настройки приложения сохранены. Нативные CHR и runtime images не менялись, дополнительных отправок вне бюджета не было. Полный успешный201 теперь дополняет partial/failed197 и отдельный resume197; исходный failed evidence сохраняется. Точная причина первого сбоя197 не установлена: pacing/новая диагностика не выдаются за доказательство его причины или исправление продуктового дефекта. Controlled receipt loss не является физическим WAN timeout/доказательством exactly-once на стороне Telegram. + +Протокол: [цельный live тест и подтверждение пользователя](ux-ui/acceptance/telegram201-live-2026-10-13.json). Следующий202 — reader API аудит секретов административных интеграций; широкие публичные IPv6/clientOS/independentWAN/scale/external jobs остаются в матрице.12.5 открыта. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 15bf3c0c..18999ad8 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-13: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-13. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-13 -Актуальное продолжение 2026-10-13: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.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: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index c47d5c55..a1b3a93a 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-13: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -38,6 +38,16 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–196 и ограничения ниже. Runtime backend/frontend ux-peak196. | +## 12.5.201 — цельный живой сценарий очереди Telegram (2026-10-13) + +Обновлён acceptance driver: ограниченный TEST label, request-start counters, safe HTTP status/accepted trace, dispatch outcome и финальная строка очереди; Telegram send pacing1500ms, отрицательные ответы provider не искажаются assertion в unknown. Драйвер не входит вtest:all, явный own DB/chat/duplicate-risk ACK обязательны, число live sends ограничено3 (resume1). Изменение только приёмочного инструмента; продуктовая очередь не менялась. + +Actual production compiled backend ux-lock200, ограниченная PostgreSQL own роль и real Portal JWT. В одном непрерывном прогоне/одной БД: duplicate dedupeKey → одна запись; два независимых sender процесса → один provider send и одна sent/history. Telegram accepted№2, receipt intentionally suppressed → unknown; повторная автоматическая диспетчеризация не отправляет. Reader retry403, missing acknowledgement400, admin version0→1 pending200, stale retry409. После подтверждённого ручного retry Telegram accepted, sent1/failed0/held0, итог две sent строки/две history. Provider принял три сообщения TEST201(IDs6/7/8); пользователь подтвердил одно№1 и два№2. + +Own DB/role/container и Portal reader user удалены, отдельный private bot file удалён; рабочие настройки приложения сохранены. Нативные CHR и runtime images не менялись, дополнительных отправок вне бюджета не было. Полный успешный201 теперь дополняет partial/failed197 и отдельный resume197; исходный failed evidence сохраняется. Точная причина первого сбоя197 не установлена: pacing/новая диагностика не выдаются за доказательство его причины или исправление продуктового дефекта. Controlled receipt loss не является физическим WAN timeout/доказательством exactly-once на стороне Telegram. + +Протокол: [цельный live тест и подтверждение пользователя](ux-ui/acceptance/telegram201-live-2026-10-13.json). Следующий202 — reader API аудит секретов административных интеграций; широкие публичные IPv6/clientOS/independentWAN/scale/external jobs остаются в матрице.12.5 открыта. + ## 12.5.200 — восстановление коллектора после падения и потери блокировки (2026-10-13) В отдельной own DB/ограниченной роли на Linux два сценария действительного сбоя: SIGKILL дочернего коллектора при удержанном ответе локального RouterOS fixture и pg_terminate_backend только собственного lock PID, выбранного по точным datname/usename/key8723105. Production PID/CHR не затрагивались. Старый production compiled ux-peak196 воспроизвёл Unhandled error event и nonzero exit при потере session-lock connection. После SIGKILL PostgreSQL освободил advisory lock, новый процесс собрал первую волну. Baseline не выдаётся за passed исправление. diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index 6e04cc2c..10b0b95f 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,16 +1,16 @@ # Оставшаяся внешняя приёмка — 2026-10-13 -Актуальное продолжение 2026-10-13: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. -Это актуальная матрица после 12.5.200. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.201. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend/frontend `ux-peak196`; 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-lock200`, frontend `ux-portal199`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | | PostgreSQL | Bootstrap, backup/restore, SQL rollback, concurrency, writer drain одного экземпляра, JWT guards и unknown commit: блоки14–24 | Несколько backend/worker экземпляров и координация всех writers; физическая потеря соединения отличается от введённого отказа подтверждения | | Speed/uptime | TCP transmit/receive/both32–33, короткий UDP34, auth failure25, transport timeout27, интерфейс after-ping28–29, snapshot/history race23–24 | Busy/abort/physical WAN disconnect; HTTP receipt socket disconnect принят97; независимое доказательство multi-WAN source/path; Home→JH/JH↔Exit с асимметричными каналами ; ROS-10 POST/SQL/GET и три часовых пояса приняты96. Короткие тесты не доказывают maximum throughput | -| Outbox | Production PG claim/dedupe/settlement/retry/JWT/browser checkpoint/a11y35–49 | Настоящий Telegram API/чат, физический timeout после возможной отправки, несколько sender процессов. Нужны тестовый бот/чат и прямое разрешение на конкретное сообщение; подменённый ответ не доказывает доставку | +| Outbox | PG claim/dedupe/settlement/retry/JWT/browser35–49; actual Telegram195/197/201, два sender процесса, controlled unknown/no-auto-repeat, explicit retry/RBAC и human receipt | Физический WAN timeout после возможной отправки и произвольный scale; controlled suppression не physical lost ACK. Первичный failed197 сохранён, whole-live201 passed | | GRE | Native lifecycle, metadata, live формы/меню/URL/Ping53–57; GRE используется в OSPF/BGP/IPsec последующих блоков; native IPv6 ULA inner109; application static IPv6 lifecycle151 | IPv6 outer, from-pool/EUI-64, независимые WAN, масштаб и длительное восстановление; принятие GRE не означает приёмку всех сценариев автоматического расписания | | WireGuard | Native handshake/data plane58, deletion60, live create/peer/disable/enable/delete62, mobile64, export/import67–74; native IPv6 ULA inner/allowedIps/handshake109; application static IPv6 lifecycle152 | Клиентские ОС и произвольные конфигурации, IPv6 outer/scale, from-pool/EUI-64 и multiple-address import/export, физический lost ACK и устойчивое восстановление; `.conf` с placeholders — шаблон, не принятый клиентский tunnel | | VXLAN | Собственная пара/private Ping/catalog/URL/export75–76; bridge/FDB/port loss/recovery107; IPv6 ULA inner по IPv4 outer108 | API приложения read-only: create/delete проверены native. IPv6 outer, масштаб/производительность, профильные mutation RBAC/concurrency отдельно не приняты | @@ -19,14 +19,14 @@ | BGP | Established83, exact /32 exchange/API/UI/administrative withdrawal92, BFD primary GRE loss/alternate/recovery93; basic native IPv6 eBGP/AFI/NLRI/Ping/withdrawal/API/UI155; native IPv6 BGP/BFD scoped withdrawal/recovery160; private4-byte ASN/as4/API/UI162 | Hold timer/TCP loss безBFD принят104; packet loss в переходе, разные внешние peers/WAN policy, basic BFDv6 принят160; IPv6 outer/public WAN/scale. Два логических пути используют тот же public WAN; physical redundancy не принята | | Recursive routes | Production PUT/change/own history restore88, disabled guards, partial/unknown/applied outcomes, live формы/контекст | Автоматический rollback/retry, durable receipts и несколько экземпляров отсутствуют; PUT не является idempotent noop. Полная произвольная legacy catalog миграция не принята | | Diagnostics/terminal | Allowlist/native reads, Ping/trace/route/MTU/DNS, actual avg-rtt, disabled guards, JWT/live PC/mobile89; real default memory tail/log limits/API/UI133 | DNS использует backend resolver; MTU — ограниченная оценка, не гарантированный максимум. Stop ожидания не доказывает остановку RouterOS команды; arbitrary CLI и physical disconnect не приняты | -| Portal/интеграции | Локальные и isolated JWT guards; UI/API error states в границах журналов | Настоящий Portal issuer/login/отзыв прав; RIPE SDK two-IP/no-fetch passed140, native IPv6 ULA flow pipeline passed145 (IPv4 transport), public IPv6 WAN/local licensed MaxMind/S3/container/certificate jobs и Gitea delivery требуют отдельных тестовых endpoints/аккаунтов. Не отправлять сообщения и не публиковать релиз без соответствующего поручения | -| Общая приёмка | Локальная12.3.83; UI1244/context221/compiled984 parity139; профильные build/E2E/live проверки последующих блоков | Traffic initial live mock-id gate passed141; IPv6 special ranges/cache passed142; unknown RIPE coordinates passed143; IPv6 synthetic UDP/worker/SQL passed144; native CHR ULA/IPFIX/API/UI passed145; ICMPv6/IPv6 endpoint labels passed146; HTTP DTO validation passed147; scoped flow catalog/serverId guards passed148; strict monthly calendar passed149; Sessions labels passed150; application GRE static IPv6 lifecycle151 passed; WireGuard static IPv6 lifecycle152 и disabled SQL/API gates passed; OSPF/BFD boundary/warning153 passed; OSPFv3 routes154 accepted in recorded bounds; BGP IPv6 basic155 passed; bigint ID/SQL guards156 passed; общая UI1260/context221/backend24 regression157 passed; IPv6 BFD correlation158 profile/deployed passed; native OSPFv3/BFDv6 boundary/recovery159 passed; BGP IPv6/BFD withdrawal/recovery160 passed; selected BGP/alert unknown guards161 replay/profiles/deployed passed (SQL stability skipped); private4-byte ASN162 native/API/UI passed; duplicate BGP alert keys163 replay/profiles/deployed passed; nullable selected BGP164 replay/profiles/API/UI passed; collector165 parallel/current guards/read-only PG passed; positive partial/error SQL166/full24 with PG passed (optional network SQL not repeated); GRE/BGP freshness167/SQL8 passed; other source audit168 выявил identity/disabled/freshness gaps; локальный server/traffic identity guard169 passed без SQL/deploy, source/per-probe/freshness170/ownSQL16/compiled1008/deployed passed; source diagnostics171/42E2E/ownSQL metadata/live2 passed; monitoring history172/ownSQL26/compiled1020/deployed passed; Ping known/error173/ownHTTP-SQL8/85uniqueE2E/native4/4/deployed passed; traffic confidence174 baseline reproduced/local guard passed; owned SQL9/9358ms/deploy175/1024compiled/live smoke passed; legacy history/provenance open; compound RTT176 local/native replay2 passed, SQL10/deploy177/1024compiled/live smoke passed; history178/legacy provenance/current TTL/manual truth/SQL9+14/35unique E2E/native GET/deployed passed; live179 complete/disable-config/bounded fallback/ownSQL10/nativeSSE2/liveUI2 passed; volume180 exact/unit marker/ownSQL6/18E2E/API/liveUI/deployed passed; binding status181 native/ownSQL9/8E2E/deployed passed; peer atomicity182 ownSQL3/native/API/UI passed; peer failure warning183 ownSQL2/4E2E/deployed passed; inactive history184 ownSQL2/deployed passed; gap185/identity186/restore187/wave188/sourceguard189/confirmed peak190 passed; async user peaks191 next; последующие изменения проверять отдельно; scoped axe не означает полную WCAG сертификацию | +| Portal/интеграции | Реальный Portal1.3.1/issuer/login/reader privacy195–196, expiry/reissue/role change/logout boundaries198, context/return_to199; actual Telegram delivery201 | Offline access JWT не отзывается logout/ролью мгновенно доexp; public IPv6 WAN, licensed MaxMind/S3/container/certificate/Gitea jobs требуют отдельных endpoints/аккаунтов. Клиентские ОС/scale отдельно | +| Общая приёмка | Локальная12.3.83; UI1244/context221/compiled984 parity139; профильные build/E2E/live проверки последующих блоков | Traffic initial live mock-id gate passed141; IPv6 special ranges/cache passed142; unknown RIPE coordinates passed143; IPv6 synthetic UDP/worker/SQL passed144; native CHR ULA/IPFIX/API/UI passed145; ICMPv6/IPv6 endpoint labels passed146; HTTP DTO validation passed147; scoped flow catalog/serverId guards passed148; strict monthly calendar passed149; Sessions labels passed150; application GRE static IPv6 lifecycle151 passed; WireGuard static IPv6 lifecycle152 и disabled SQL/API gates passed; OSPF/BFD boundary/warning153 passed; OSPFv3 routes154 accepted in recorded bounds; BGP IPv6 basic155 passed; bigint ID/SQL guards156 passed; общая UI1260/context221/backend24 regression157 passed; IPv6 BFD correlation158 profile/deployed passed; native OSPFv3/BFDv6 boundary/recovery159 passed; BGP IPv6/BFD withdrawal/recovery160 passed; selected BGP/alert unknown guards161 replay/profiles/deployed passed (SQL stability skipped); private4-byte ASN162 native/API/UI passed; duplicate BGP alert keys163 replay/profiles/deployed passed; nullable selected BGP164 replay/profiles/API/UI passed; collector165 parallel/current guards/read-only PG passed; positive partial/error SQL166/full24 with PG passed (optional network SQL not repeated); GRE/BGP freshness167/SQL8 passed; other source audit168 выявил identity/disabled/freshness gaps; локальный server/traffic identity guard169 passed без SQL/deploy, source/per-probe/freshness170/ownSQL16/compiled1008/deployed passed; source diagnostics171/42E2E/ownSQL metadata/live2 passed; monitoring history172/ownSQL26/compiled1020/deployed passed; Ping known/error173/ownHTTP-SQL8/85uniqueE2E/native4/4/deployed passed; traffic confidence174 baseline reproduced/local guard passed; owned SQL9/9358ms/deploy175/1024compiled/live smoke passed; legacy history/provenance open; compound RTT176 local/native replay2 passed, SQL10/deploy177/1024compiled/live smoke passed; history178/legacy provenance/current TTL/manual truth/SQL9+14/35unique E2E/native GET/deployed passed; live179 complete/disable-config/bounded fallback/ownSQL10/nativeSSE2/liveUI2 passed; volume180 exact/unit marker/ownSQL6/18E2E/API/liveUI/deployed passed; binding status181 native/ownSQL9/8E2E/deployed passed; peer atomicity182 ownSQL3/native/API/UI passed; peer failure warning183 ownSQL2/4E2E/deployed passed; inactive history184 ownSQL2/deployed passed; gap185/identity186/restore187/wave188/sourceguard189/confirmed peak190 passed; aggregate peaks191, request dedupe193, cross-process lock194/200, full regression192 (1286 unique E2E и25-й профиль privacy196 scoped), Portal195–199/Telegram201 passed; последующие изменения проверять отдельно; scoped axe не означает полную WCAG сертификацию | Доказательства и точные ограничения: [полная история этапа12](ux-ui-stage-12.md), [внешний протокол](ux-ui-external-acceptance.md), [BGP93](ux-ui/acceptance/bgp-failover-2026-10-10.json), [паспорт стенда](ux-ui-test-server.md). Невыполненные пункты не являются все блокерами данного лабораторного сценария: для выпуска необходимо явно определить требуемые конфигурации и принять их либо согласовать ограничение. ## Следующая последовательность — 2026-10-13 -1. **201 — цельный Telegram live:**3 сообщения, pacing/trace, own DB; первичный failure197 не скрывать.200 crash/observed lock-loss принят с границами fencing/network partition. +1. **202 — reader API secrets:** административные integrations/config endpoints, чтение с реальным reader JWT; проверить masking/permissions без изменения credentials/config. 2. **Профильный контроль:** для новых изменений выполнять затронутые SQL/API/UI проверки. Общая регрессия192 выполнена; не повторять её без изменений общей основы или нового основания. 3. **Внешние зависимости:** Portal issuer/login/revoke, Telegram bot/chat/разрешённое сообщение, клиентские ОС, независимые WAN/public IPv6 и scale/multi-instance — отдельные группы по таблице выше. Ограничения текущего стенда не превращать в обещание приёмки всех конфигураций. @@ -1362,3 +1362,13 @@ Production compiled ux-lock200 на own DB: SIGKILL recovery passed; lock connec Протоколы: [baseline](ux-ui/acceptance/lifecycle200-baseline-result.json), [fixed lifecycle](ux-ui/acceptance/lifecycle200-fixed-result.json), [SQL profile](ux-ui/acceptance/owned200-result.json), [compiled](ux-ui/acceptance/compiled200-result.json), [deployment/bounds](ux-ui/acceptance/lock200-deployment-2026-10-13.json), [live traffic](ux-ui/acceptance/traffic-lock200-deployed-2026-10-13.json). Следующий201: цельный Telegram live197 с диагностикой начала requests/response codes/dispatch outcome/status и ограничением3 сообщений в собственном чате. Controlled lost receipt остаётся имитацией; первоначальный failed evidence не удалять.12.5 открыта. + +## 12.5.201 — цельный живой сценарий очереди Telegram (2026-10-13) + +Обновлён acceptance driver: ограниченный TEST label, request-start counters, safe HTTP status/accepted trace, dispatch outcome и финальная строка очереди; Telegram send pacing1500ms, отрицательные ответы provider не искажаются assertion в unknown. Драйвер не входит вtest:all, явный own DB/chat/duplicate-risk ACK обязательны, число live sends ограничено3 (resume1). Изменение только приёмочного инструмента; продуктовая очередь не менялась. + +Actual production compiled backend ux-lock200, ограниченная PostgreSQL own роль и real Portal JWT. В одном непрерывном прогоне/одной БД: duplicate dedupeKey → одна запись; два независимых sender процесса → один provider send и одна sent/history. Telegram accepted№2, receipt intentionally suppressed → unknown; повторная автоматическая диспетчеризация не отправляет. Reader retry403, missing acknowledgement400, admin version0→1 pending200, stale retry409. После подтверждённого ручного retry Telegram accepted, sent1/failed0/held0, итог две sent строки/две history. Provider принял три сообщения TEST201(IDs6/7/8); пользователь подтвердил одно№1 и два№2. + +Own DB/role/container и Portal reader user удалены, отдельный private bot file удалён; рабочие настройки приложения сохранены. Нативные CHR и runtime images не менялись, дополнительных отправок вне бюджета не было. Полный успешный201 теперь дополняет partial/failed197 и отдельный resume197; исходный failed evidence сохраняется. Точная причина первого сбоя197 не установлена: pacing/новая диагностика не выдаются за доказательство его причины или исправление продуктового дефекта. Controlled receipt loss не является физическим WAN timeout/доказательством exactly-once на стороне Telegram. + +Протокол: [цельный live тест и подтверждение пользователя](ux-ui/acceptance/telegram201-live-2026-10-13.json). Следующий202 — reader API аудит секретов административных интеграций; широкие публичные IPv6/clientOS/independentWAN/scale/external jobs остаются в матрице.12.5 открыта. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index ee224f8c..52c27656 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: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -3751,3 +3751,13 @@ Production compiled ux-lock200 на own DB: SIGKILL recovery passed; lock connec Протоколы: [baseline](ux-ui/acceptance/lifecycle200-baseline-result.json), [fixed lifecycle](ux-ui/acceptance/lifecycle200-fixed-result.json), [SQL profile](ux-ui/acceptance/owned200-result.json), [compiled](ux-ui/acceptance/compiled200-result.json), [deployment/bounds](ux-ui/acceptance/lock200-deployment-2026-10-13.json), [live traffic](ux-ui/acceptance/traffic-lock200-deployed-2026-10-13.json). Следующий201: цельный Telegram live197 с диагностикой начала requests/response codes/dispatch outcome/status и ограничением3 сообщений в собственном чате. Controlled lost receipt остаётся имитацией; первоначальный failed evidence не удалять.12.5 открыта. + +## 12.5.201 — цельный живой сценарий очереди Telegram (2026-10-13) + +Обновлён acceptance driver: ограниченный TEST label, request-start counters, safe HTTP status/accepted trace, dispatch outcome и финальная строка очереди; Telegram send pacing1500ms, отрицательные ответы provider не искажаются assertion в unknown. Драйвер не входит вtest:all, явный own DB/chat/duplicate-risk ACK обязательны, число live sends ограничено3 (resume1). Изменение только приёмочного инструмента; продуктовая очередь не менялась. + +Actual production compiled backend ux-lock200, ограниченная PostgreSQL own роль и real Portal JWT. В одном непрерывном прогоне/одной БД: duplicate dedupeKey → одна запись; два независимых sender процесса → один provider send и одна sent/history. Telegram accepted№2, receipt intentionally suppressed → unknown; повторная автоматическая диспетчеризация не отправляет. Reader retry403, missing acknowledgement400, admin version0→1 pending200, stale retry409. После подтверждённого ручного retry Telegram accepted, sent1/failed0/held0, итог две sent строки/две history. Provider принял три сообщения TEST201(IDs6/7/8); пользователь подтвердил одно№1 и два№2. + +Own DB/role/container и Portal reader user удалены, отдельный private bot file удалён; рабочие настройки приложения сохранены. Нативные CHR и runtime images не менялись, дополнительных отправок вне бюджета не было. Полный успешный201 теперь дополняет partial/failed197 и отдельный resume197; исходный failed evidence сохраняется. Точная причина первого сбоя197 не установлена: pacing/новая диагностика не выдаются за доказательство его причины или исправление продуктового дефекта. Controlled receipt loss не является физическим WAN timeout/доказательством exactly-once на стороне Telegram. + +Протокол: [цельный live тест и подтверждение пользователя](ux-ui/acceptance/telegram201-live-2026-10-13.json). Следующий202 — reader API аудит секретов административных интеграций; широкие публичные IPv6/clientOS/independentWAN/scale/external jobs остаются в матрице.12.5 открыта. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 5b0e6e19..087af65c 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: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. | Параметр | Проверенное состояние | | --- | --- | @@ -708,7 +708,7 @@ flowchart LR ## 12.5.77 — основной блок IPsec (2026-10-09) -Актуальное продолжение 2026-10-13: завершён200 — baseline lock-loss crash воспроизведён, исправленный collector survives/aborts stale run/recovery passed.71 owned SQL + concurrency/57603ms,1044 compiled matched, live traffic API/UI2 passed. Runtime backend ux-lock200/frontend ux-portal199. Следующий201 — цельный Telegram live с расширенной диагностикой и ограниченным бюджетом3 сообщений.12.5 открыта. +Актуальное продолжение 2026-10-13: завершён201 — цельный real Telegram outbox/dedupe/two senders/unknown/no-auto-repeat/manual acknowledged retry passed в одной own DB; пользователь подтвердил1×№1+2×№2.200 collector crash/observed lock-loss fixed/deployed. Backend ux-lock200/frontend ux-portal199/Portal1.3.1. Следующий202 — reader API аудит секретов в административных интеграциях.12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). @@ -2177,3 +2177,13 @@ Production compiled ux-lock200 на own DB: SIGKILL recovery passed; lock connec Протоколы: [baseline](ux-ui/acceptance/lifecycle200-baseline-result.json), [fixed lifecycle](ux-ui/acceptance/lifecycle200-fixed-result.json), [SQL profile](ux-ui/acceptance/owned200-result.json), [compiled](ux-ui/acceptance/compiled200-result.json), [deployment/bounds](ux-ui/acceptance/lock200-deployment-2026-10-13.json), [live traffic](ux-ui/acceptance/traffic-lock200-deployed-2026-10-13.json). Следующий201: цельный Telegram live197 с диагностикой начала requests/response codes/dispatch outcome/status и ограничением3 сообщений в собственном чате. Controlled lost receipt остаётся имитацией; первоначальный failed evidence не удалять.12.5 открыта. + +## 12.5.201 — цельный живой сценарий очереди Telegram (2026-10-13) + +Обновлён acceptance driver: ограниченный TEST label, request-start counters, safe HTTP status/accepted trace, dispatch outcome и финальная строка очереди; Telegram send pacing1500ms, отрицательные ответы provider не искажаются assertion в unknown. Драйвер не входит вtest:all, явный own DB/chat/duplicate-risk ACK обязательны, число live sends ограничено3 (resume1). Изменение только приёмочного инструмента; продуктовая очередь не менялась. + +Actual production compiled backend ux-lock200, ограниченная PostgreSQL own роль и real Portal JWT. В одном непрерывном прогоне/одной БД: duplicate dedupeKey → одна запись; два независимых sender процесса → один provider send и одна sent/history. Telegram accepted№2, receipt intentionally suppressed → unknown; повторная автоматическая диспетчеризация не отправляет. Reader retry403, missing acknowledgement400, admin version0→1 pending200, stale retry409. После подтверждённого ручного retry Telegram accepted, sent1/failed0/held0, итог две sent строки/две history. Provider принял три сообщения TEST201(IDs6/7/8); пользователь подтвердил одно№1 и два№2. + +Own DB/role/container и Portal reader user удалены, отдельный private bot file удалён; рабочие настройки приложения сохранены. Нативные CHR и runtime images не менялись, дополнительных отправок вне бюджета не было. Полный успешный201 теперь дополняет partial/failed197 и отдельный resume197; исходный failed evidence сохраняется. Точная причина первого сбоя197 не установлена: pacing/новая диагностика не выдаются за доказательство его причины или исправление продуктового дефекта. Controlled receipt loss не является физическим WAN timeout/доказательством exactly-once на стороне Telegram. + +Протокол: [цельный live тест и подтверждение пользователя](ux-ui/acceptance/telegram201-live-2026-10-13.json). Следующий202 — reader API аудит секретов административных интеграций; широкие публичные IPv6/clientOS/independentWAN/scale/external jobs остаются в матрице.12.5 открыта. diff --git a/docs/ux-ui/acceptance/telegram201-live-2026-10-13.json b/docs/ux-ui/acceptance/telegram201-live-2026-10-13.json new file mode 100644 index 00000000..e8c02d13 --- /dev/null +++ b/docs/ux-ui/acceptance/telegram201-live-2026-10-13.json @@ -0,0 +1,87 @@ +{ + "date": "2026-10-13", + "block": "12.5.201", + "database": "mm_accept_166_1791883314948", + "resumeOnly": false, + "scope": "Production compiled outbox, owned PostgreSQL, actual Portal JWT and real Telegram provider", + "cases": [ + { + "name": "dedupe and independent senders", + "senders": 2, + "queuedRows": 1, + "providerSends": 1, + "sentHistoryRows": 1 + }, + { + "name": "controlled lost receipt", + "providerAccepted": true, + "status": "unknown", + "automaticResend": false, + "physicalDisconnect": false + }, + { + "name": "explicit retry with real Portal JWT", + "reader": 403, + "missingAck": 400, + "admin": 200, + "staleVersion": 409, + "resolutionVersion": 1, + "intentionalDuplicate": true, + "sentHistoryRows": 2 + } + ], + "providerSendCalls": 3, + "requestTrace": [ + { + "requestNumber": 2, + "startedAt": "2026-10-13T09:22:05.935Z", + "httpStatus": 200, + "providerAccepted": true, + "receiptSuppressed": true + }, + { + "requestNumber": 3, + "startedAt": "2026-10-13T09:22:07.435Z", + "httpStatus": 200, + "providerAccepted": true + } + ], + "providerAcceptanceIds": [ + 6, + 7, + 8 + ], + "ownPortalUsersRemoved": true, + "passed": true, + "retryDiagnostic": { + "outcome": { + "sent": 1, + "failed": 0, + "held": 0, + "errors": [] + }, + "rows": [ + { + "status": "sent", + "retry_count": 0, + "resolution_version": 1, + "next_attempt_at": "2026-10-13T09:22:06.181Z", + "last_error": null + } + ] + }, + "humanReceipt": { + "confirmed": true, + "message1": 1, + "message2": 2 + }, + "cleanup": { + "ownedDatabaseRoleContainerRemoved": true, + "ownPortalUsersRemoved": true, + "temporaryBotPrivateFileRemoved": true + }, + "limitations": [ + "Controlled receipt suppression after actual provider acceptance, not physical WAN timeout", + "Full scenario passed with 1500ms pacing; cause of the initial failed run197 remains unproven" + ] +}