610 lines
61 KiB
Plaintext
610 lines
61 KiB
Plaintext
DM — аудит документации и контрактов, 26–27.10.2026
|
||
|
||
База: /home/user/utun2, HEAD 03b050949cf36cc4868324be94a54eaddfdd494c.
|
||
Задание: /home/user/utun-doc-audit-checklist.txt, раздел src/dm/ и связанные документы.
|
||
|
||
Текущий статус на 27.10.2026: аудит контрактов DM завершён, 10/10 файлов [V].
|
||
Итог — раздел12; разделы1–11 сохраняют историю промежуточных проверок и исправлений.
|
||
|
||
1. Объём и статус
|
||
|
||
Полностью прочитаны dm_core.c/.h, dm_crypto.c/.h и dm_history.c/.h, doc/dm_arch.md,
|
||
doc/pm.txt и doc/pm_invites.md. Просмотрены заголовки media/mailbox owners, lifecycle
|
||
в utun_instance и участок media_forget_prepare/committed. Это не полный аудит этих owners.
|
||
dm_crypto.h [V]; dm_core.h/dm_history.h/doc/dm_arch.md [~].
|
||
dm_mailbox.h/dm_mailbox_media.h/dm_media.h/dm_media_priv.h сохраняют [ ].
|
||
doc/pm_invites.md сохраняет [~]; doc/pm.txt [ ]: нормативные требования прочитаны,
|
||
но соответствие всей доставки и хранения пока не проверено.
|
||
|
||
Уточнены контракты nonce, native-endian wire/длин, lifecycle, commit исходящей задачи,
|
||
JSON и локального удаления/поколений. В pm_invites исправлен формат события результата:
|
||
36 байт с generation вместо прежних 28. Платформенные реализации целиком не проверялись.
|
||
|
||
2. Исходный дефект: ошибка загрузки сбрасывает счётчики существующей беседы
|
||
|
||
dm_conv_load возвращает -1 при отсутствии строки и при ошибках prepare/step,
|
||
повреждённых ключах либо отказе X25519. dm_start проверяет только ==0, а иначе
|
||
обнуляет dm_conv, заполняет ключи и сохраняет через dm_conv_save.
|
||
ON CONFLICT обновляет last_out_seq/last_in_seq/last_ts из обнулённой структуры.
|
||
Ошибка чтения тем самым превращается в успешную запись с потерей счётчиков.
|
||
|
||
Проверка использует настоящие utun_core/chat_service, SQLite и OpenSSL, отдельные
|
||
БД в /tmp, штатные dm_start/dm_send/dm_accept_message. Исходные сообщения принимаются
|
||
обычным публичным API. SQLite authorizer однократно отказывает в чтении
|
||
dm_conversations.peer_node_id; последующие операции разрешены. Production-файлы,
|
||
архивы и объекты для воспроизведения не подменялись.
|
||
|
||
Положительный контроль: повторный dm_start без отказа сохраняет out=1,in=2.
|
||
При одном SQLITE_DENY: dm_conv_load пишет ERROR с точной причиной, затем dm_start
|
||
пишет INFO started, возвращает 0; out=1->0,in=2->0, обе строки dm_messages остаются.
|
||
Проверка ожидаемого отказа/сохранности даёт FAIL, exit2; tracked allocations0->0.
|
||
Существующей диагностики вместе с журналом инъекции и SQL-снимком достаточно
|
||
для однозначного вывода: это ошибка ветвления, не ошибка расшифровки или транспорта.
|
||
|
||
Последствия: пока исходящая строка seq=1 сохранена, новая отправка того же номера
|
||
будет конфликтовать с историей. После локального удаления история очищается,
|
||
а сброшенный счётчик сохраняется; повтор seq при неизменном ключе воспроизведёт
|
||
детерминированный nonce. Это вывод из кода, повторная отправка после сбоя в стенде
|
||
не выполнялась. Раскрытие содержимого/эксплуатация не проверялись.
|
||
|
||
В dm_accept_message и dm_invite_trampoline также смешаны отсутствие и ошибка
|
||
dm_conv_load; их отказные сценарии в этом этапе отдельно не воспроизводились.
|
||
|
||
Простой план исправления: выделить результаты FOUND/NOT_FOUND/ERROR для загрузки;
|
||
считать NOT_FOUND только завершённый SELECT без строки, ошибки логировать и
|
||
передавать без UPSERT/события успеха. Просмотреть все callers, включая dm_media;
|
||
при найденной беседе не обновлять seq из пустой структуры. Регрессии должны
|
||
проверить prepare/step/короткие ключи/crypto, сохранность полей и generation/hidden,
|
||
повторный запуск, успешное создание отсутствующей беседы и нормальное продолжение seq.
|
||
Новый формат протокола или БД для исправления не требуется.
|
||
|
||
3. Проверки и артефакты первоначального аудита, до исправления
|
||
|
||
Сборка штатных шести целей через tests/Makefile — PASS.
|
||
test_dm/test_dm_history/test_dm_e2e/test_dm_invite/test_dm_media/test_dm_worker:6/6 PASS.
|
||
Полные логи прочитаны; ERROR в штатных отрицательных проверках ожидаемы.
|
||
Worker:24 запуска,49 heartbeat,max_gap11.3мс. Media:phase9 PASS.
|
||
Эти тесты не покрывают подтверждённый отказ загрузки беседы.
|
||
|
||
/tmp/dm-audit-baseline-build.log
|
||
/tmp/dm-audit-baseline-results.log
|
||
/tmp/dm-audit-baseline-test_dm{,_history,_e2e,_invite,_media,_worker}.log
|
||
/tmp/dm-audit-load-failure.c и /tmp/dm-audit-load-failure.mk
|
||
/tmp/dm-audit-load-failure-build.log
|
||
/tmp/dm-audit-load-failure.log (контроль PASS, сохранность при отказе FAIL, exit2)
|
||
|
||
Первый запуск стенда в sandbox остановился до DM на запрете netlink-сокета.
|
||
Окончательные стенд и штатные тесты запущены с разрешением вне sandbox;
|
||
сетевые настройки хоста не менялись. Пользовательская БД не использовалась.
|
||
|
||
Рабочий алгоритм, протокол, БД и штатные тесты не менялись: только документы/комментарии.
|
||
Новые полный check.sh, ASAN/UBSan/LSan, GUI/Android/Windows/FreeBSD не запускались.
|
||
По AGENTS.md:10 аудит остановлен на подтверждённом дефекте до его исправления;
|
||
открытая задача внесена в doc/tasks.md. Коммит/push не выполнялись.
|
||
|
||
4. Исправление по запросу пользователя — 26.10.2026
|
||
|
||
dm_conv_load теперь возвращает FOUND/NOT_FOUND/ERROR. Только SQLITE_DONE без строки
|
||
и с успешным finalize означает NOT_FOUND; SQL-ошибки prepare/bind/step/finalize,
|
||
короткие ключи и отказ X25519 означают ERROR. Полная структура выдаётся только
|
||
после успешного завершения загрузки/вывода ключа. Лог содержит conv/rc/SQL-причину,
|
||
успешная загрузка с seq доступна в TRACE, отсутствие записи — DEBUG.
|
||
|
||
Проверены все5 callers: dm_start и dm_accept_message возвращают ошибку без
|
||
создания/сохранения/открытия беседы, dm_invite_trampoline завершает запрос
|
||
DM_INVITE_START_ERROR без повторного dm_start; dm_send и JSON требуют FOUND.
|
||
В dm_start также перестала игнорироваться ошибка сохранения выбранной области.
|
||
Медиа не вызывает dm_conv_load и не создаёт беседу вместо ошибочной загрузки:
|
||
dm_send_file отклоняет ошибки чтения/ключей до регистрации worker/файлов.
|
||
Протокол и формат БД не менялись.
|
||
|
||
Постоянная Linux-регрессия test_dm_load включена в check_PROGRAMS.
|
||
35 комбинаций5 callers×7 отказов для видимой беседы, ещё35 после локального удаления,
|
||
4 отказа отдельной media-подготовки и5 отказов открытия отсутствующей беседы:79 PASS.
|
||
Отказы:prepare/bind/step/finalize,короткие X25519/Ed25519 BLOB,EVP_PKEY_derive.
|
||
Проверяются SHA256 всех полей7 DM-таблиц,sqlite3_total_changes,autocommit,
|
||
отсутствие событий успеха и неизменённый буфер квитанции при отказе приёма.
|
||
Нормальные контроли:создание отсутствующей беседы,повторное открытие после restart,
|
||
продолжение исходящего seq1->2 и приём впервые доставленного seq1 после seq2.
|
||
Запрос invite проверяется на настоящей собственной CHAT-группе; общая доставка
|
||
и создание беседы при первом входящем сообщении покрываются штатными E2E/media-тестами.
|
||
|
||
Новая регрессия с прежним dm_core.c из HEAD ожидаемо FAIL на первом prepare-отказе:
|
||
ошибка -> dm_start0,дополнительные SQL-write/CONV_UPDATED;cleanup allocations0->0.
|
||
Использовались отдельные /tmp/old-core.o и бинарник; рабочий архив не подменялся.
|
||
Первоначальный стенд с настоящим SQLITE_DENY теперь PASS:dm_start=-1,out1->1,in2->2,
|
||
две строки истории сохранены,allocations0->0. Оба контрольных лога прочитаны полностью.
|
||
|
||
Сборка Linux PASS; DM-профиль test_dm_load/dm/history/e2e/invite/media/worker7/7 PASS.
|
||
ASAN/UBSan/LSan тот же профиль7/7 PASS с detect_leaks=1/halt_on_error=1.
|
||
Отдельная копия /tmp/utun-dm-load-sanitizers:новая сборка core/libuasync/Opus
|
||
с согласованными -fsanitize=address,undefined,без смешивания обычных объектов.
|
||
dm_core.c,test_dm_load.c,tests/Makefile.am побайтно совпадают с рабочими.
|
||
Проверены все sanitizer-логи:нет отчётов ASAN/UBSan/LSan;test_dm_load allocations0->0.
|
||
|
||
Первый полный check.sh:202 passed,1 failed,0 skipped (203 total).
|
||
Отказ test_chat_join_e2e:happy A!=C,J не декодировал приглашение,потом A/C не нашли J;
|
||
degraded и invalid-key PASS. Отдельный диагностический повтор3/3 PASS.
|
||
Код теста создаёт link.txt до записи/закрытия;читатель ждёт только access(F_OK).
|
||
Это возможная гонка тестовой публикации,но конкретная причина исходного отказа
|
||
не доказана без размеров/результатов чтения. Отдельная задача в doc/tasks.md;
|
||
production JOIN и критерии/код теста не менялись,первый отказ сохранён.
|
||
|
||
Окончательный повтор полного check.sh:203 passed,0 failed,0 skipped;exit0,175с.
|
||
Интеграции proxy9/9,burst1/1,load8/8 PASS,134217728 проверенных байт.
|
||
В этом прогоне новый test_dm_load PASS;код после профильных проверок не менялся.
|
||
Повторный успех не закрывает отдельную задачу диагностики исходного отказа JOIN.
|
||
|
||
Логи исправления:
|
||
/tmp/dm-load-fix-build.log (окончательная сборка PASS)
|
||
/tmp/dm-load-fix-profile-results.log и /tmp/dm-load-fix-test_dm*.log
|
||
/tmp/dm-load-fix-controls-results.log и /tmp/dm-load-fix-control-*.log
|
||
/tmp/dm-load-fix-negative-build.log и /tmp/dm-load-fix-original-build.log
|
||
/tmp/dm-load-fix-sanitizers-build.log,/tmp/dm-load-fix-sanitizers-results.log,
|
||
/tmp/dm-load-fix-sanitizers-test_dm*.log,/tmp/dm-load-fix-final-verification.log
|
||
/tmp/dm-load-fix-full-check-first.log,/tmp/dm-load-fix-join-first.log,/tmp/dm-load-fix-join-repeat.log
|
||
/tmp/dm-load-fix-full-check.log,/tmp/dm-load-fix-netns.log,/tmp/dm-load-fix-repeat-netns.log
|
||
|
||
Полный набор запускается в отдельном IPv6 network namespace без изменения сети хоста.
|
||
Начальные ошибки подготовки sanitizer-копии (недостающие generated auxiliary files/
|
||
etcpmon header и ограничение LSan в sandbox) устранены до успешной сборки/прогона.
|
||
В первом native build не хватало openssl/evp.h в новом тесте;добавлен до успешной сборки.
|
||
GUI/Android/Windows/FreeBSD не запускались;регрессия с linker wrappers — Linux.
|
||
Дефект счётчиков исправлен;исходные частичные отметки аудита остальных DM owners сохраняются.
|
||
Коммит/push не выполнялись.
|
||
|
||
5. Исходный отказ mailbox/media — 26.10.2026: transient SQL становится постоянным отказом M
|
||
|
||
Прочитаны полностью dm_mailbox.c,dm_mailbox_media.c,dm_media.c и четыре заголовка,
|
||
связанные file_transfer/media_async контракты,lifecycle instance и штатный test_dm_media.
|
||
Уточнены uasync/ownership/lifecycle,семантика принятия PUT,транзакция регистрации media,
|
||
предусловия размеров control,ограничение рассылки до64 S на группу и SQL-helper ownership.
|
||
Четыре новых заголовка отмечаются[~]:чтение завершено,но полный аудит контрактов/отказов
|
||
и документация media API не завершены. Прежние core/history/dm_arch[~],crypto[V] сохраняются.
|
||
|
||
Дефект в dm_custody_store:результат SELECT COALESCE(sum(cipher_size),0) FROM dm_custody
|
||
при любом rc!=SQLITE_ROW превращается в used=UINT64_MAX. Следующая ветка used>quota
|
||
выдаёт DM_MEDIA_REJECT reason1,то есть утверждает реальное переполнение квоты.
|
||
Оригинальная причина SQL не логируется;WARN показывает фиктивный used18446744073709551615.
|
||
dm_mailbox_media_recv на S сохраняет released=1 и holder=0. dm_job_storage исключает
|
||
все прежние назначения через NOT IN(SELECT node_id FROM dm_media_holders WHERE id=?),
|
||
включая released. Поэтому повторные STORE на этом M для UUID больше не возникают.
|
||
|
||
Доказательство:/tmp/dm-quota-audit.c/.mk,временный вариант штатного test_dm_media.
|
||
Настоящие четыре utun/chat ядра A/B/S/M,разные БД,подписанные channel/member/admin-блоки,
|
||
реальные UDP-транспорты и file_transfer. Сначала штатная прямая доставка и прежние
|
||
проверки rollback/реальной квоты;затем B останавливается,A отправляет новое вложение.
|
||
Прикладной алгоритм,архивы,production-объекты и штатный тест не подменялись.
|
||
Linker-wrapper однократно возвращает SQLITE_IOERR только для used-space SELECT в БД M.
|
||
В обеих проверках настроено1024МиБ,текущая custody пуста;ciphertext запрашивает98385байт.
|
||
|
||
Контроль без отказа:назначение M->custody reserved->файл сохранён->STORED на S.
|
||
Через16 календарных секунд тестовых часов:ready1,released0,waiting0,holders1,used98385;
|
||
phase9 PASS,exit0,allocations0->0.
|
||
Fault:SQLITE_IOERR->quota refused usedUINT64_MAX requested98385 quota1073741824,
|
||
затем storage refused reason1 на S. Через16с:ready0,released1,waiting1,holders1,used0;
|
||
quota-запрос STORE выполнен только один раз (финальный диагностический SELECT в счётчик не включён).
|
||
phase4 ожидаемо FAIL,exit1,allocations0->0. После однократного отказа SQLite работает;
|
||
возобновления назначения нет. Persistent-исключение после restart следует из таблицы/SQL,
|
||
отдельный restart в этом стенде не выполнялся.
|
||
|
||
Логи:/tmp/dm-quota-audit-build.log,/tmp/dm-quota-audit-results.log,
|
||
/tmp/dm-quota-audit-control.log и /tmp/dm-quota-audit-fault.log.
|
||
Ключевые строки всех переходов сохранены в /tmp/dm-quota-audit-diagnostics.log.
|
||
В baseline protocol_checks ожидаемы отдельный SQL-trigger rollback и настоящий
|
||
quota-отказ2МиБ при квоте1МиБ:они происходят до включения fault и не являются новым дефектом.
|
||
Работающие transport/media callbacks и SQL-снимки однозначно показывают механизм;
|
||
production-диагностика должна дополнительно различать SQL-ошибку и настоящую квоту.
|
||
|
||
Простое исправление:проверять результат чтения занятого места отдельно,логировать
|
||
ошибки SQL с rc/причиной и возвращаться без REJECT. Сохранённый holder/stored0 на S
|
||
уже обеспечивает повтор STORE через существующий таймер. Реально недостаточная
|
||
квота сохраняет нынешний REJECT,выбор другого M и учёт всех назначений.
|
||
Также проверить bind/finalize,не выдавать operational-ошибку за quota refusal.
|
||
Постоянная регрессия:однократные SQL-отказы не исключают свободный M,последующий
|
||
STORE сохраняет ciphertext;реальная квота по-прежнему отклоняет запрос до загрузки.
|
||
Новый протокол/формат БД/специальный control для retry не требуется.
|
||
|
||
По AGENTS.md:10 аудит остановлен до исправления;открытая задача в doc/tasks.md.
|
||
В этом этапе изменены только комментарии/документы/отметки;исправление dm_conv_load
|
||
и новая постоянная регрессия из предыдущего этапа сохранены. Новые fullcheck/ASAN/UBSan/LSan,
|
||
GUI/Android/Windows/FreeBSD не запускались;прежние203/203 и sanitizer7/7 относятся
|
||
к предыдущему исправлению,а не к новому отказу custody. Коммит/push не выполнялись.
|
||
|
||
6. Исправление quota-admission — 26.10.2026
|
||
|
||
По запросу пользователя dm_custody_store проверяет чтение занятого места и finalize
|
||
до сравнения с квотой. Ошибка prepare уже возвращалась без ответа;теперь ошибка step,
|
||
неожиданный SQLITE_DONE и ошибка finalize также прекращают STORE без REJECT/регистрации.
|
||
Лог step/finalize содержит rc,SQL-причину и указание на сохранённый повтор STORE.
|
||
Прежнее назначение M остаётся на S;его штатный таймер повторяет STORE. Настоящий
|
||
недостаток квоты по-прежнему выдаёт reason1. У агрегатного SELECT нет bind-параметров.
|
||
Протокол,формат БД и алгоритм назначения S не менялись.
|
||
|
||
Постоянный test_dm_media расширен fault wrappers только для Linux:
|
||
- Отдельные prepare/step/finalize/неожиданный DONE проверяют один отказ за вызов,
|
||
отсутствие REJECT/STORED,отсутствие изменений SQL в S/M,пустые custody/tombstones,
|
||
autocommit. Достаточная квота настроена1024МиБ;отказ не заменяется успешной регистрацией.
|
||
- Настоящее превышение квоты требует ровно один REJECT без STORED/регистрации custody.
|
||
- Сетевой сценарий использует прежние4 ядра,подписанные роли,настоящие UDP/router/transfer.
|
||
После отключения B первые3 STORE получают разные SQL-ошибки на M:prepare,step,finalize.
|
||
Четвёртый STORE сохраняет файл на том же M;REJECT0,STORED1,одно назначение,released0.
|
||
Последующие штатные проверки перезапуска S/M при выключенном A,точного файла у B,
|
||
квитанций,удаления промежуточной копии/тела S,поздних STORE/STORED и TTL сохранены.
|
||
Исходные4 сбоя проверяют обработчик после router,сетевой retry идёт обычным транспортом.
|
||
|
||
Нативный и sanitizer-профили7/7 PASS:test_dm_load/dm/history/e2e/invite/media/worker.
|
||
В test_dm_media phase9 PASS,allocations0->0;в native/sanitizer одинаковая последовательность
|
||
hits3,STORE4,REJECT0,STORED1,holders1. ASAN/UBSan/LSan7/7 PASS,detect_leaks=1,
|
||
halt_on_error=1;ядро,libuasync и встроенный Opus собраны с одинаковыми sanitizer-флагами.
|
||
Использована отдельная копия /tmp/utun-dm-quota-sanitizers;обычные объекты не подменялись.
|
||
Побайтно сверены dm_media.c/test_dm_media.c/tests/Makefile.am и прежние dm_core.c/test_dm_load.c.
|
||
|
||
Контроли:
|
||
- Новый test_dm_media с dm_media.c из HEAD ожидаемо FAIL,exit1:step-отказ даёт ложный
|
||
REJECT,который ловит новая проверка. allocations0->0. Старый модуль собран отдельным
|
||
объектом и включён в отдельный бинарник;рабочий libutun.a не подменялся.
|
||
- Исходный /tmp/dm-quota-audit.c с одним SQLITE_IOERR и исправленным core:phase9 PASS,exit0.
|
||
- test_dm_media без DM_QUOTA_FAULT_INJECTION:штатный сценарий phase9 PASS,exit0.
|
||
Это Linux-компиляция без wrappers;runtime других ОС не проверялся.
|
||
Все3 контроля восстанавливают tracked allocations до0. Полные логи изменённого
|
||
media-теста/native/sanitizer/контролей прочитаны;ожидаемые ERROR относятся к инъекциям.
|
||
|
||
Артефакты:
|
||
/tmp/dm-quota-fix-build.log
|
||
/tmp/dm-quota-fix-profile-results.log,/tmp/dm-quota-fix-test_dm*.log
|
||
/tmp/dm-quota-fix-sanitizers-build.log,/tmp/dm-quota-fix-sanitizers-results.log,
|
||
/tmp/dm-quota-fix-sanitizers-test_dm*.log
|
||
/tmp/dm-quota-fix-controls-build.log,/tmp/dm-quota-fix-controls-results.log,
|
||
/tmp/dm-quota-fix-control-{test_dm_media_old,dm-quota-fixed-original,test_dm_media_no_injection}.log
|
||
/tmp/dm-quota-fix-final-verification.log
|
||
/tmp/dm-quota-fix-full-check.log,/tmp/dm-quota-fix-netns.log
|
||
|
||
Полный check.sh203/203 PASS,0 failed/0 skipped;proxy9/9,burst1/1,load8/8 PASS,
|
||
134217728 проверенных байт,exit0,176с. Этот прогон включает новую fault/retry-проверку media.
|
||
Набор выполнен в отдельном IPv6 network namespace;сеть хоста не менялась.
|
||
Первый сборочный запуск отдельного negative-control не включал test_clock.o в линковку;
|
||
временная make-цель исправлена до контрольных прогонов. Основная сборка/код от этого не менялись.
|
||
Документация обновлена,задача quota-admission закрыта. Остальные отметки аудита DM остаются
|
||
частичными;GUI/Android/Windows/FreeBSD не запускались. Коммит/push не выполнялись.
|
||
|
||
7. Commit/rebase/push по запросу пользователя — 26.10.2026
|
||
|
||
Все накопленные изменения DM сохранены в2ae1990d. Fetch обнаружил8 новых коммитов
|
||
origin/master поверх03b05094:изменения headless PCM,документации звонков и их проверок.
|
||
Rebase на03be46c3 завершён с единственным конфликтом doc/tasks.md:сохранены обе
|
||
полные группы задач. tests/Makefile.am объединился автоматически,цели test_dm_load,
|
||
quota wrappers test_dm_media и upstream test_call_headless_queue присутствуют.
|
||
DM .c/.h и обе новые/расширенные регрессии побайтно сохранены относительно исходного коммита.
|
||
|
||
После rebase коммит стал b6588d059455ed430c902a325af7d010f15f3475.
|
||
Нативная сборка PASS;новый полный check.sh204/204 PASS,0 failed/0 skipped,
|
||
proxy9/9,burst1/1,load8/8 PASS,134217728 байт,exit0,175с. Включён новый upstream
|
||
test_call_headless_queue (11/11) и все DM-регрессии. Сеть — отдельный IPv6 namespace.
|
||
Push origin master:03be46c3..b6588d05 PASS,без force. git ls-remote подтвердил hash,
|
||
HEAD==origin/master,рабочее дерево после push было чистым.
|
||
Логи:/tmp/dm-audit-rebase-build.log,/tmp/dm-audit-rebase-full-check.log,
|
||
/tmp/dm-audit-rebase-netns.log. Санитайзеры после rebase заново не запускались;
|
||
исходные DM-файлы по сравнению с прошедшим sanitizer-профилем не менялись.
|
||
|
||
8. Продолжение: UTF-8 имя повреждается при построении беседы
|
||
|
||
Продолжены сверка core/history,передачи поколения и путей из attachment_send,
|
||
участков headless/GUI/JNI вызывающих функций. Это чтение кода,не аппаратная проверка UI.
|
||
Уточнён dm_send_file:0 означает вызов submit,который вправе синхронно вызвать callback
|
||
ошибки;результат подготовки сообщается событием. Это исправление описания возврата.
|
||
|
||
Новый подтверждённый дефект:dm_conv.peer_name[64],snprintf в dm_start/dm_conv_load
|
||
режут имя по63байтам,без проверки границы UTF-8. json_escape передаёт получившиеся
|
||
байты в JSON без проверки/исправления. Корректное входное имя тем самым повреждается
|
||
в SQLite,а dm_list_conversations_json возвращает0 с некорректным UTF-8 JSON.
|
||
dm_start_req допускает до127байт имени;отсутствует предусловие ASCII/<=63байт.
|
||
|
||
Стенд:/tmp/dm-utf8-audit.c/.mk. Настоящие core/chat_service/SQLite/X25519,
|
||
отдельные ключи для трёх собеседников,новая БД/tmp;публичные dm_start/list API.
|
||
Валидные входы:ASCII63байта;31×«Я»=62байта;32×«Я»=64байта.
|
||
Контроли ASCII63/UTF8_62 дают корректный UTF-8 JSON. UTF8_64 сохраняется как63байта,
|
||
последний байт0xd0 без продолжения;start=0,list=0. Строгий Python decode JSON
|
||
даёт invalid continuation byte на позиции537;проверка exit2. SQL-readonly-снимок
|
||
подтверждает тот же обрыв в сохранённом peer_name,tail_hex=afd0afd0afd0afd0.
|
||
Tracked allocations0->0;собственно C-стенд exit0,отказ обнаруживает независимый валидатор.
|
||
Сам runtime-лог тоже содержит этот некорректный байт:валидатор читает диагностический
|
||
лог с replacement только для поиска ASCII-путей,но JSON и SQL BLOB проверяет строго.
|
||
|
||
Причина однозначна по точным входным/сохранённым длинам и байтам;это не ошибка JSON
|
||
парсера,шифрования или вывода терминала. Повторная загрузка имени через dm_conv_load
|
||
имеет то же побайтовое усечение;этот путь в новом стенде отдельно не запускался.
|
||
|
||
Простой план:определить единое ограничение имени и копировать только целые UTF-8
|
||
code points. Проверять входы и уже сохранённые некорректные строки с диагностикой;
|
||
увеличение массива само по себе не решает обрыв на новой границе.
|
||
Постоянные проверки:ASCII и2/3/4-байтовые символы до/на/за границей,SQL round-trip,
|
||
повторная загрузка и строгая декодируемость JSON. До выбора обработки уже повреждённых
|
||
имён (безопасное усечение/отказ) рабочая реализация не менялась.
|
||
|
||
Логи:/tmp/dm-utf8-audit-build.log,/tmp/dm-utf8-audit-runtime.log,
|
||
/tmp/dm-utf8-audit-validation.log;валидатор:/tmp/dm-utf8-audit-validate.py.
|
||
По AGENTS.md:10 дальнейший аудит остановлен,задача открыта в doc/tasks.md.
|
||
В продолжении только комментарии/документы,все текущие частичные отметки сохранены.
|
||
Предыдущий check204 проверял объединённые исправления,а не обработку нового имени;
|
||
новые sanitizer/GUI/Android/Windows/FreeBSD проверки не запускались.
|
||
|
||
9. Исправление UTF-8 имени собеседника
|
||
|
||
Предел имени явно задан DM_PEER_NAME_MAX=63 байта без NUL. Единый dm_copy_peer_name
|
||
сохраняет целые UTF-8 code points при dm_start, dm_conv_load, автосоздании во входящем
|
||
dm_accept_message и построении снимка бесед. Входящее имя из nodes сначала читается
|
||
в128байт, чтобы прежнее предварительное усечение в64байта не портило символ.
|
||
JSON нормализует как SQL peer_name,так и fallback из nodes при пустом имени.
|
||
|
||
Некорректная последовательность,overlong,surrogate,значение выше U+10FFFF или NUL
|
||
внутри SQL TEXT обрывают имя перед первым недопустимым code point. WARN содержит
|
||
conv_id,смещение и исходную длину;обычное усечение длинного имени отмечается DEBUG.
|
||
Чтение/снимок не исправляют SQL автоматически. Следующая штатная запись беседы
|
||
сохраняет уже нормализованное имя;формат БД/wire и счётчики сообщений не меняются.
|
||
|
||
Постоянный test_dm_names добавлен в штатный набор tests/Makefile.am:
|
||
68 случаев с реальными core/chat_service/SQLite и отдельными ключами собеседников.
|
||
ASCII0/1/62/63/64/127байт;границы2/3/4-байтовых символов до/на/за63байтами,
|
||
повторяющиеся символы,включая U+10FFFF;12 видов некорректных последовательностей
|
||
с пустым/непустым префиксом;SQL TEXT с NUL;кавычки/слеш/newline и кириллица.
|
||
Каждый случай проверяет точные SQL/JSON имена при создании,чтении повреждённого
|
||
сохранённого имени,load через чтение сообщений,load/save через dm_send и fallback.
|
||
total_changes и исходные SQL-байты подтверждают отсутствие скрытых записей при чтении.
|
||
Отдельно проверен restart с той же БД/идентичностью;allocations0->0.
|
||
|
||
Независимый строгий Python decode UTF-8 + json.loads проверил273 полных снимка,
|
||
9452 строки бесед и предел63байта на каждое имя;PASS в native и sanitizer сборках.
|
||
Контроль с прежним core:новая регрессия FAIL,exit1,на чтении длинного SQL-имени
|
||
после первых4 случаев (прежний JSON обходил предел);allocations0->0.
|
||
Исходный стенд раздела8 повторён на исправленном core:ASCII63/UTF8_62/UTF8_64 PASS,
|
||
32×«Я» сохраняются как62байта,строгий JSON всех3 снимков корректен,allocations0->0.
|
||
Исходные доказательства дефекта сохранены в прежних /tmp/dm-utf8-audit-*.log.
|
||
|
||
Нативная сборка PASS;DM-профиль8/8 PASS: names/load/crypto/history/e2e/invite/media/worker.
|
||
ASAN/UBSan/LSan8/8 PASS,detect_leaks=1,halt_on_error=1;отчётов о памяти/UB/утечках нет.
|
||
Изолированная копия /tmp/utun-dm-utf8-sanitizers синхронизирована с текущими исходниками,
|
||
включая upstream call_headless;ASAN/UBSan-ссылки проверены в core/libuasync/Opus.
|
||
Полный check.sh205/205 PASS,0 failed/0 skipped,proxy9/9,burst1/1,load8/8,
|
||
134217728байт,exit0,172с. Сеть — отдельный IPv6 namespace,сеть хоста не менялась.
|
||
|
||
Логи:/tmp/dm-utf8-fix-{build,profile-results,test_dm_names,negative-build,negative}.log,
|
||
/tmp/dm-utf8-fix-{original-build,original,original-validation,json-validation}.log,
|
||
/tmp/dm-utf8-fix-{sanitizers-build,sanitizers-results,sanitizers-test_dm*,full-check,netns}.log.
|
||
Задача UTF-8 закрыта;общий аудит DM остаётся частичным:crypto[V],остальные6headers
|
||
и dm_arch[~]. Платформенные GUI/Android/Windows/FreeBSD проверки не выполнялись.
|
||
|
||
Финальная сверка перед отправкой:fetch принёс4 Android mute-коммита до fa76447f.
|
||
Rebase прошёл без конфликтов;DM исходники/headers,Makefile и регрессия побайтно
|
||
сохранены. Коммиты исправления/отчёта после rebase:d09ed031/87d24b72.
|
||
Повторная native сборка PASS;check.sh205/205 PASS,0 failed/0 skipped,proxy9/9,
|
||
burst1/1,load8/8 PASS,134217728байт,exit0,175с. Строгие273 JSON/9452строки снова PASS.
|
||
Логи:/tmp/dm-utf8-fix-rebase-{build,full-check,json-validation,netns}.log.
|
||
Санитайзеры после rebase не повторялись:DM runtime не менялся,общий call_audio.h
|
||
в upstream изменяет только комментарий;новые платформенные Android callers этим
|
||
DM-профилем не проверяются. Upstream задачи/отчёты Android mute сохранены целиком.
|
||
|
||
10. Продолжение mailbox: SQL-ошибка оставляет завершённое TTL-назначение активным
|
||
|
||
База продолжения:3dc5eb502db6964fc6467385cc65db9d1df83c44,рабочее дерево было чистым.
|
||
Повторно сверены dm_mailbox.c/.h,dm_mailbox_media.c/.h и относящиеся к квитанциям,
|
||
контролю и TTL функции dm_media. Приём PUT проверяет точное тело,роль S и общую
|
||
группу;квитанция текста и удаление pending объединены транзакцией. Это чтение
|
||
соответствующих путей,не полная проверка всех SQL/allocator/платформенных отказов.
|
||
|
||
Подтверждён новый дефект:dm_mailbox_media_recv в EXPIRED сначала делает
|
||
UPDATE dm_media_holders SET released=1,затем отдельным statement обновляет job:
|
||
holder=0,stored=0,expired=1,retry_at=0. При отказе второго statement первое изменение
|
||
остаётся в БД. Таймер при недоступном B видит прежние holder и stored=1,поэтому
|
||
не выбирает нового M,не повторяет STORE и не сверяет expires с текущим временем.
|
||
На M custody уже удалена;dm_custody_done хранит tombstone,но таймер эту таблицу
|
||
не сканирует и не повторяет уведомление EXPIRED сам по себе.
|
||
|
||
Стенд:/tmp/dm-expiry-audit.c/.mk — отдельный вариант штатного test_dm_media.
|
||
Настоящие4 ядра A/B/S/M с подписанными мемберскими/административными блоками,
|
||
разными SQLite,реальными UDP/BGP/file_transfer и прежними проверками доставки.
|
||
Штатные quota-fault проверки идут в обоих прогонах одинаково;новая инъекция только
|
||
на S и только на UPDATE завершения EXPIRED,однократно SQLITE_IOERR в sqlite3_step.
|
||
Рабочие C,штатные тесты,объекты и libutun не подменялись;данные только в/tmp.
|
||
|
||
Оба прогона сначала проходят прямую доставку,offline custody и восстановление
|
||
S/M с выключенным A,побайтную доставку B и удаление промежуточной копии.
|
||
Затем B снова выключен;для третьего файла настроен TTL1с на M. M успевает принять
|
||
98385байт ciphertext,подтвердить хранение,по TTL удалить custody и послать EXPIRED.
|
||
|
||
Контроль без новой инъекции:phase9 PASS,exit0,allocations0->0. Для seq3 на S
|
||
holder0,stored0,expired1;назначение released1. На M нет custody,есть expired tombstone.
|
||
Fault:UPDATE завершается rc10,hit1,ошибка логируется вместе с точным SQL. После
|
||
ещё16 календарных секунд тестовых часов и нескольких успешных повторов PUT:
|
||
на S holder723190674248656275,stored1,expired0,expires1793032708,receiptNULL,body сохранён;
|
||
для того же UUID E20AC64A2660882CE73D68D48E2AFFA0 назначение этого M released1.
|
||
На M custody0,expired tombstone1. Phase8 FAIL,exit1,allocations0->0.
|
||
В runtime released=2 считает также прежнее успешно доставленное назначение;
|
||
независимый readonly SQL JOIN отдельно подтвердил released1 для проверяемого UUID.
|
||
Остановка/освобождение owners штатные,не маскируют сохранённое расхождение.
|
||
|
||
Окно отсутствия восстановления16с проверено исполнением;отсутствие пути восстановления
|
||
при продолжающемся offline B следует также из ветки таймера. Restart после этой
|
||
инъекции,возврат B и дополнительный storage не запускались;потеря до TTL не заявляется.
|
||
Это нарушение согласованности durable состояния после SQL-отказа,а не ошибка самого
|
||
удаления по TTL:копия M удалена в предусмотренный срок.
|
||
|
||
Направление исправления:идемпотентный восстанавливаемый переход EXPIRED с согласованным
|
||
состоянием job/holder;подтверждённое назначение проверять таймером по сохранённому expires.
|
||
Одного BEGIN/COMMIT вокруг двух UPDATE недостаточно:при rollback событие уже потреблено,
|
||
а M не повторит EXPIRED после удаления custody. Нужны отказные проверки обоих statement,
|
||
commit и восстановления после restart;поздний STORED не должен отменить завершение.
|
||
Сходная последовательность REJECT/DELETE_ACK замечена при чтении,но отдельный runtime
|
||
её отказов в этом продолжении не выполнен. Конкретная реализация пока не менялась.
|
||
|
||
Сборка отдельного стенда PASS. Логи:/tmp/dm-expiry-audit-{build,control,fault,validation}.log;
|
||
полные журналы сохранены,DM-выборки без транспортного шума — *-control-dm.log/*-fault-dm.log.
|
||
Прежний check205/санитайзеры относятся к исправлению UTF-8 и не покрывали этот отказ.
|
||
Новые fullcheck/sanitizer/GUI/Android/Windows/FreeBSD проверки не выполнялись.
|
||
По AGENTS.md:10 дальнейший аудит остановлен;задача открыта в doc/tasks.md.
|
||
В продолжении только комментарий контракта и отчёт/задача;частичные отметки сохранены.
|
||
|
||
11. Исправление восстанавливаемого завершения TTL
|
||
|
||
На S добавлен единый dm_job_release для EXPIRED/REJECT:BEGIN IMMEDIATE,освобождение
|
||
назначения и сброс текущего holder/stored,COMMIT. Prepare/bind/step/finalize обоих
|
||
statement и COMMIT проверяются;при ошибке ROLLBACK,без сообщения об успешном переходе.
|
||
Лог ошибки содержит M,rc/finalize,точный SQL и причину;успех — M,причину expired/rejected
|
||
и отдельные счётчики изменения назначения/job. Идемпотентный повтор не пишет released
|
||
заново;старый M не сбрасывает нового holder. WHERE receipt IS NULL сохраняет приоритет
|
||
подписанной квитанции B. DELETE_ACK остаётся отдельным одношаговым освобождением.
|
||
|
||
Таймер S независимо проверяет сохранённый expires подтверждённого stored-назначения.
|
||
При истечении выполняет тот же переход и перечитывает job после commit;ошибка остаётся
|
||
на следующем retry_at. Это работает при offline B,потерянном EXPIRED и после restart.
|
||
Для ещё не подтверждённого хранения STORE продолжает повторяться;M отвечает из
|
||
custody/tombstone. Поэтому для отсутствующего STORED новый механизм не требует
|
||
выдуманного срока хранения. Формат таблиц/wire,подписи и TTL на M не менялись.
|
||
Лог удаления тела S уточнён:освобождены все назначения. Завершение TTL не утверждает,
|
||
что worker M уже закончил физическое удаление в тот же момент;его владелец и повторы
|
||
сохраняются на M. Неистёкшие назначения продолжают удаляться до DELETE_ACK.
|
||
|
||
Штатный Linux test_dm_media расширен,без отдельной подмены production:
|
||
18 component-сценариев на настоящем job S:EXPIRED и REJECT × prepare/bind/step/finalize
|
||
обоих UPDATE и COMMIT. После каждого отказа сравниваются все6 полей назначения/job
|
||
(holder,stored,expired,expires,retry_at,released),проверяется autocommit;нормальный повтор
|
||
завершает переход,дубликат и поздний STORED не меняют результат и не создают receipt.
|
||
Фикстура возвращается синхронно до следующего uasync callback;это component-проверка
|
||
SQL/control,не утверждение о реальном удалении M на каждом из18 искусственных событий.
|
||
|
||
Сетевой TTL-сценарий использует настоящие4 ядра A/B/S/M и прежний полный путь
|
||
offline-файла с restart S/M при выключенном A,точным файлом на B и удалением копий.
|
||
Затем B отключён,на M TTL1с. EXPIRED от M намеренно теряется,SQL-сброс job на S
|
||
блокируется до удаления custody M. Проверены сохранённый holder/stored и released0
|
||
после rollback;S перезапускается. Без получения EXPIRED таймер S восстанавливает
|
||
holder0,stored0,expired1,released1. Поздний STORED с будущим expires и STORE не
|
||
возрождают назначение/файл и не выдают ложную квитанцию доставки.
|
||
После restart поздний component-control ждёт реального восстановления ETCP-линка.
|
||
Native и ASAN:18 checks,один заблокированный сброс,два потерянных EXPIRED (включая
|
||
ответ на поздний STORE),restart1,phase9 PASS,allocations0->0.
|
||
|
||
Независимое readonly чтение SQLite по точному UUID подтвердило на M custody0,
|
||
expired tombstone1;на S holder0/stored0/expired1,receiptNULL,body сохранён и released1.
|
||
Прежний job seq2 сохранил квитанцию и удалённое тело. Проверено и в sanitizer-копии.
|
||
Прежний координатор в отдельном /tmp/dm-expiry-old-coordinator.o/бинарнике ожидаемо FAIL
|
||
новой регрессии на bind-отказе первого UPDATE:частичный переход,phase4,exit1,
|
||
allocations0->0. Рабочий libutun не подменялся. Исходный one-shot IOERR-стенд раздела10
|
||
повторён на исправлении:matching SQL дополнен receipt IS NULL,hit1,затем успешный
|
||
переход,phase9 PASS,exit0,allocations0->0;исходные доказательства дефекта сохранены.
|
||
|
||
Нативная сборка PASS;DM-профиль names/load/crypto/history/e2e/invite/media/worker8/8 PASS.
|
||
ASAN/UBSan/LSan8/8 PASS,detect_leaks=1,halt_on_error=1;отчётов памяти/UB/утечек нет.
|
||
Изолированная /tmp/utun-dm-expiry-sanitizers побайтно совпадает с проверяемыми
|
||
dm_mailbox_media.c/.h,tests/Makefile.am/test_dm_media.c;core/libuasync/Opus содержат
|
||
ASAN/UBSan-инструментацию. В media-логе при restart один packet too small for init
|
||
size68;прогон восстановил линк и завершился,это не отчёт санитайзера.
|
||
Первую сборку запустил до завершения изменения linker flags,она отказала на
|
||
__real_sqlite3_bind_blob. После окончания правок повторная полная сборка и отдельная
|
||
сборка media PASS;проверки выполнялись на согласованных окончательных объектах.
|
||
|
||
Полный check.sh205/205 PASS,0 failed/0 skipped;proxy9/9,burst1/1,load8/8 PASS,
|
||
134217728байт,exit0,173с. Сеть — отдельный IPv6 namespace,настройки хоста не менялись.
|
||
Логи:/tmp/dm-expiry-fix-{final-build,media-build,profile-results,test_dm*,validation}.log,
|
||
/tmp/dm-expiry-fix-{negative-build,negative,original-build,original}.log,
|
||
/tmp/dm-expiry-fix-{sanitizers-build,sanitizers-results,sanitizers-test_dm*,full-check,netns}.log.
|
||
Задача завершения TTL закрыта. Общий аудит DM частичный;прежние отметки сохраняются.
|
||
GUI/Android/Windows/FreeBSD не проверялись;DELETE_ACK fault matrix отдельно не добавлялась.
|
||
|
||
12. Завершение аудита контрактов DM — 27.10.2026
|
||
|
||
База заключительного этапа: /home/user/utun4, master, исходный HEAD07f63c3047b4a9bef6c568ca590d3fefde95816f.
|
||
Полностью сверены все семь заголовков src/dm/ с реализациями core, crypto, history,
|
||
mailbox, mailbox_media и media; doc/dm_arch.md, doc/pm.txt и doc/pm_invites.md.
|
||
Это завершение проверки описаний/API, не утверждение об отсутствии всех возможных
|
||
ошибок программы. Новых подтверждённых дефектов выполнения в этом этапе нет.
|
||
|
||
В заголовках уточнены:
|
||
- Заимствование аргументов, один освобождаемый блок запросов UI, жизнь instance,
|
||
поток uasync и запрет доступа workers к SQLite/сети.
|
||
- Проверка тела/подписи отдельно от области router/ролей, точные повторы и конфликты,
|
||
границы транзакций при send/accept, подпись квитанции после commit входящего сообщения.
|
||
- Независимые квитанции сообщения и файла; STORED не удаляет исходящий outbox.
|
||
- Форматы DM/mailbox/media control, native-endian чисел и big-endian attachment_info,
|
||
лимиты send data с descriptor и размеры выходных буферов квитанций.
|
||
- Поколения/hidden, сохранение ключей и seq, отпечатки удалённых тел, отмена старых
|
||
invite/transfer и отбрасывание завершения worker старого поколения.
|
||
- Роли S/M, выбор нового storage без прежних назначений, фиксация назначения до STORE,
|
||
local S/M control и отличие передачи пакета от durable приёма.
|
||
- File holds, манифест путей, busy=-1 уборщика, повтор удаления и fsync каталога;
|
||
пользовательский исходник не передаётся уборке без явного remove_source.
|
||
- Запуск mailbox/core/media и остановка quiesce -> media_async drain -> destroy
|
||
с живыми SQLite/группами, сохранение данных между stop/restart.
|
||
|
||
dm_arch согласован с порциями таймеров32/8, обычным retry5с и отдельными retry3600с/30с,
|
||
сохранённым retry_at текстовых очередей и сбросом медиа при restart. Добавлены wire
|
||
таблица, порядок владельцев и восстановление оригинала после EXPIRED: срок копии M
|
||
не запрещает B получить исходный файл A; поздний EXPIRED не портит готовый файл.
|
||
pm.txt дополнен привязкой требований к текущим owners/ролям/настройкам, dm_arch
|
||
больше не называет этот аудит частичным. Исторические результаты сборок помечены датой.
|
||
|
||
Сверены относящиеся к контрактам callers: chat_service_start/stop, attachment_send,
|
||
file_transfer lookup/cancel, Qt DmInviteDialog/MainWindow/MessageList и bridge,
|
||
Android JNI/ViewModel/PmInviteDialog, headless DM handlers, регистрация JOIN-ключей
|
||
и планирование member_sync после JOIN_READY/принятия участника.
|
||
Клиентский код просмотрен для описанных DM-событий/выбора адресата/подготовки файла;
|
||
полный аудит Qt/Android и остальных общих модулей этим не заявляется.
|
||
pm_invites описывает владение запросом, поколение до регистрации и отсутствие
|
||
отката открытой беседы при последующей ошибке; отмена PM не отзывает JOIN-ключ.
|
||
|
||
Проверки текущего этапа:
|
||
- make -C src -j4 и сборка всех девяти существующих DM-целей: PASS.
|
||
- Native test_dm/history/names/load/e2e/invite/media/worker/media_cleanup:9/9 PASS.
|
||
test_dm_load:79 проверок; names:68 случаев и273 снимка, независимый Python JSON
|
||
parser прочитал каждый полный снимок. Worker:25 запусков,50 heartbeat,max_gap11.3мс.
|
||
Media:phase12,6266 heartbeat,allocations0->0; проверены11 retirement SQL faults,
|
||
18 release faults, потерянные control/restart и возврат точного оригинала после TTL.
|
||
- Linux cleanup component:13 SQL faults для scan/ACK/body, повтор после restart,
|
||
несколько M, потерянный/повторный/чужой ACK и поздний STORED; exit0.
|
||
Сеть перехвачена, receipt задан фикстурой; криптографию и физическое удаление M
|
||
проверяет отдельный test_dm_media. Одношаговый autocommit может уже завершиться
|
||
до искусственного finalize failure; тест проверяет это состояние и идемпотентный повтор.
|
||
- Каждый из семи заголовков: C99 и C++20 с -Wall -Wextra -Werror,14/14 PASS.
|
||
Для private/media C API C++ использует extern "C", как существующие клиенты;
|
||
include path lib/ соответствует проекту и предоставляет sqlite3.h.
|
||
- Все C-файлы DM побайтно совпадают с начальным снимком; C-токены всех заголовков
|
||
совпадают после исключения комментариев/пробелов. Алгоритмы, API/ABI, wire и SQL
|
||
этим этапом не менялись. git diff --check PASS; новые тесты не добавлялись.
|
||
|
||
Логи и снимки: /tmp/dm-contract-finish-before/sha256.json,
|
||
/tmp/dm-contract-finish-{build,final-core-build,final-tests-build,headers,validation}.log,
|
||
/tmp/dm-contract-finish-native-{results,test_dm*}.log; исходные тела/JSON — в test artifacts.
|
||
Сетевой профиль выполнен вне sandbox. Первый sandbox-запуск cleanup вернул exit0,
|
||
но uasync сообщил Operation not permitted при создании служебного fd; окончательный
|
||
повтор вне sandbox прошёл без этих сообщений. Сетевые настройки хоста не менялись.
|
||
Новые full check.sh, ASAN/UBSan/LSan, сборки/интерактив Qt/Android/Windows/FreeBSD
|
||
не выполнялись; прежние результаты не приписываются заключительному прогону.
|
||
Изменения radio и doc/tasks.md сохранены отдельно от DM-коммитов; push не выполнялся.
|
||
|
||
13. Rebase перед push — 27.10.2026
|
||
|
||
После отказа push (origin содержал новые коммиты) пользователь запросил rebase.
|
||
Получен origin/master492f6adc; все шесть DM-коммитов перенесены на эту базу.
|
||
Единственный конфликт — dm_messages_req в dm_core.h: сохранены generation из origin
|
||
и проверенные комментарии. Остальные пять патчей перенесены без изменения по range-diff.
|
||
Старые хеши и результаты раздела12 относятся к состоянию до переноса.
|
||
|
||
В origin появился generation в запросе истории и CHAT_EVT_DM_MESSAGES:
|
||
[conv_len:1][conv][generation:8][JSON]. Сверены полный trampoline, проверка current,
|
||
новая регрессия test_dm_history и получение снимка Qt/Android. dm_arch уточнён под
|
||
этот формат. Все C-файлы DM побайтно совпадают с новым origin; токены семи заголовков
|
||
совпадают после исключения комментариев/пробелов. C99/C++20:14/14 PASS.
|
||
|
||
Перед rebase сохранены21 незакоммиченных radio-файл, включая untracked, в stash
|
||
и отдельной резервной копии с SHA256/режимами. После переноса восстановлены все21:
|
||
18 файлов побайтно, doc/tasks.md/tests/Makefile.am/tools/chatgui/CMakeLists.txt
|
||
слиты с origin; списки добавленных/удалённых строк radio точно совпали с сохранёнными.
|
||
Повторная проверка после сборки также PASS; radio не включается в DM-коммиты.
|
||
|
||
Свежий ./build.sh --no-gui -j4:PASS. После пересборки native DM9/9 PASS,
|
||
включая скрытые/устаревшие запросы истории и точное поколение опубликованного снимка.
|
||
Дополнительно radio/radio_mesh/radio_headless/radio_headless_queue4/4 PASS.
|
||
Это профиль13 бинарников, не полный check.sh; новые GUI/Android/sanitizer прогоны
|
||
не выполнялись. Радио EOS C++-профиль не повторялся, его исходники сохранены побайтно.
|
||
Логи:/tmp/utun4-dm-rebase-{build,results,radio-preservation,test_*}.log.
|
||
Резервная копия указана в /tmp/utun4-dm-rebase-backup-path.txt.
|