From 7649981cbc264b65cb7e5b753b47393efe849f4e Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 27 Oct 2026 00:39:18 +0100 Subject: [PATCH] Describe committed author decisions and rollback lifecycle --- doc/encrypted_attachments.md | 30 ++++++++++++++++++++++-------- doc/service_lifecycle.md | 2 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/doc/encrypted_attachments.md b/doc/encrypted_attachments.md index 0fde5260..d614aa7e 100644 --- a/doc/encrypted_attachments.md +++ b/doc/encrypted_attachments.md @@ -137,14 +137,16 @@ REQUEST=1, REQUEST_ACK=2, GRANT=3, DENY=4, RESULT_ACK=5 контейнера. Конфликтующие ключи и результаты отклоняются. REQUEST_ACK отправляется после сохранения запроса. GRANT/DENY появляются -в outbox при сохранении решения. В этой авторской операции обнаружен отдельный дефект: -`chat_attachment_decide` проверяет изменение состояния, но не число строк записи outbox. -Пропуск INSERT через `RAISE(IGNORE)` даёт успех и событие UI с решением без GRANT в очереди; -получатель после REQUEST_ACK уже не повторяет запрос, перезапуск автора очередь не восстанавливает. -Кроме того, SAVEPOINT внутри внешней транзакции даёт успех и событие до её commit; -внешний rollback затем отменяет решение и исходящий ответ. Оба случая воспроизведены на -локальной сети A–S–B/C; исправление этой операции ещё не выполнено. -Доказательства и границы проверки — в [chat_audit_findings.txt](chat_audit_findings.txt), «Аудит решения автора». +в outbox в одной собственной BEGIN IMMEDIATE/COMMIT с решением автора. Проверка прав +также выполняется внутри неё. Изменяется ровно один входящий запрос в state=0; +уже принятое решение повторной командой не заменяется. Общий помощник записи outbox +проверяет prepare, все bind, step, ровно одну строку и finalize, транзакцией управляет вызывающий. +Внешняя транзакция отклоняется до проверки прав и остаётся нетронутой. SQL-отказ, +включая пропуск записи через RAISE(IGNORE), сохраняет прежние состояние и очередь. +Возврат0 и единственное уведомление UI следуют после проверенного commit; доставка +выполняется позже. Trampoline при ошибке отправляет событие с success=0, позволяя повторить команду. +Неудачный rollback с открытой транзакцией отключает модуль и запрашивает stop ядра после poll. +История дефекта и исправления — в [chat_audit_findings.txt](chat_audit_findings.txt). Ответы REQUEST_ACK/GRANT/DENY/RESULT_ACK применяются собственной короткой транзакцией: чтение запроса и очереди, запись ключа @@ -187,10 +189,22 @@ backpressure и повтором через 5 секунд; restart продол Дополнительно проверяются настоящий commit veto, INSERT ABORT/IGNORE, внешняя транзакция, синхронный отказ запуска, restart с опубликованным ключом и отказ rollback с закрытием БД владельцем. +`test_attachment_decisions` проверяет116 SQL-отказов/повторов выдачи и отказа, с пустой +и существующей очередью: чтение подписанного мембера, допуск автора, запись состояния, +outbox, BEGIN/COMMIT. Участник имеет настоящие join/invitation подписи, сообщение +сохранено штатным chat_core; запись локального вложения создаётся фикстурой. +Readonly-соединение в событии проверяет committed ключ/состояние/команду/retry_at/created_at +и сохранность соседнего ключа. Дополнительно: настоящий commit veto, ABORT/IGNORE для +UPDATE состояния и INSERT/UPDATE очереди, внешняя транзакция, удалённый мембер, +неверное направление и повторное решение, один GUI event, остановка при отказе rollback. + `test_encrypted_attachment`: реальные A–S–B/C, скачивание с S при выключенном A, перезапуски автора с запросами и получателя с ключом, выдача B и отказ C, отсутствие ключа на S/C, отрицательные control-пакеты, повтор GRANT, восстановление удалённого plaintext без нового согласия и удаление канала. +На Linux пропуск GRANT outbox и внешняя транзакция автора отвергаются без изменения +ожидающего запроса и без события. После restart автора повтор решения сохраняет +state+outbox; отдельное readonly-соединение подтверждает их в момент единственного события UI. На Linux первый bind полученного GRANT намеренно возвращает SQLITE_NOMEM: проверяются полный откат и отсутствие ACK, сохранение GRANT у автора, затем реальная повторная выдача и расшифровка. Перед каждым RESULT_ACK получателя отдельное readonly-соединение видит ключ. diff --git a/doc/service_lifecycle.md b/doc/service_lifecycle.md index 5af5f1f8..0c77360a 100644 --- a/doc/service_lifecycle.md +++ b/doc/service_lifecycle.md @@ -37,7 +37,7 @@ Desktop и Android проверяют `instance->running` вместе со св включая Android-цикл после restart. Запрос из callback завершает цикл после возврата из текущего poll; уже начатая обработка остальных callbacks этого poll не прерывается. Владелец затем снимает media-привязки, уничтожает ядро и освобождает uasync. -Это используется также при отказе rollback авторской подготовки вложения или применения ответа о ключе, если SQL-транзакция +Это используется также при отказе rollback подготовки вложения, решения автора или применения ответа о ключе, если SQL-транзакция осталась открыта: модуль вложений предварительно прекращает приём и снимает свой таймер/router. Create уже подготавливает listeners, топологию/SQLite, router/proxy и мониторинг;