diff --git a/src/chat/member_sync_doc.md b/src/chat/member_sync_doc.md index b0bc1aba7..40756f4ae 100644 --- a/src/chat/member_sync_doc.md +++ b/src/chat/member_sync_doc.md @@ -1,6 +1,6 @@ # member_sync — адаптер участников каналов -Поверх [merkle_sync](merkle_sync_doc.md) синхронизирует source=0 записи таблиц peers_ +Поверх [merkle_sync](merkle_sync_doc.md) синхронизирует опубликованные source=0 записи таблиц peers_ и подписанную политику приглашений. Правила допуска и переподписи: [group_invite_policy](../../doc/group_invite_policy.txt). Транспортный движок не занимается подписями и версиями участников. @@ -27,10 +27,26 @@ ver — каноническая десятичная строка1..INT_MAX,б Удаление используется для повреждённых записей. Конфликт одинаковых версий с разным содержимым не разрешается порядком доставки: отсутствие прогресса завершает Merkle-раунд ошибкой конфликта. -Входящая страница сначала целиком проверяется на корректность раскладки, длин и строк. -Затем записи применяются под savepoint member_page. Ошибка откатывает всю страницу вместе с индексом. -Уведомления GUI/топологии и changed выполняются после commit. Производное admitted -при приёме страниц пересчитывается после MT_OK, с сохранением предыдущего допуска до этой точки. +Входящая страница целиком проверяется на раскладку, длины, строки и границы листа/курсора. +Новые версии сохраняются в той же peers-таблице: record_state=1, sync_id своего обмена, +previous_id прежней записи, sync_record с исходным wire. Служебная строка node_id=0 +хранит подписанную политику; её AUTOINCREMENT id даёт уникальный sync_id. +Сервисы, GUI, исходящие страницы и Merkle видят только record_state=0. + +После получения всех различий BEGIN IMMEDIATE копирует актуальные опубликованные строки +в бэкап record_state=2 этого обмена. Сравнение версий, проверка подписей/цепочек, +выбор новой записи или валидного бэкапа, admitted, общие идентичности и индексы +входят в одну транзакцию. Если обе версии неверны, удаляется только этот участник. +Подписанное исключение остаётся валидной записью; даже повреждение профиля не стирает +независимый более свежий owner-блок при его восстановлении. Исключение самого узла +закрывает доступ, но не удаляет остальные записи. Неполная цепочка или SQL/crypto-отказ +откатывают обмен без разрушения прежнего состава. Уведомления идут после commit. + +Параллельные обмены не видят pending друг друга. Поздний обмен сравнивается с текущей, +а не начальной версией: свежие изменения и отзывы не откатываются. Отмена удаляет +только свой sync_id; перезапуск удаляет все незавершённые версии. Формат peers изменён +без миграции старых таблиц: неподдерживаемая схема явно отклоняется. + Каждый member_sync_apply_record также имеет savepoint, поэтому ошибка пересчёта не оставляет запись без индекса. Неудачный ROLLBACK TO не сопровождается RELEASE частичных данных:собственная операция пробует полный ROLLBACK,при чужой транзакции полный откат обязан выполнить caller. @@ -75,7 +91,7 @@ CHAT-группы и уведомляет props-потребителей; общ и повторно вызвать очистку; stop/destroy выполняются вне callbacks. Локальный верификатор возвращает 1 (сохранить), 0 (доказанная порча), -1 (операционная ошибка). -Отсутствие подписи/ожидаемой зависимости сохраняет запись; отказ SQL/OpenSSL не считается +Отсутствие ожидаемой зависимости сохраняет запись; отказ SQL/OpenSSL не считается доказательством неверной подписи. verify_signature отдельно различает MS_VERIFY_DEFERRED и MS_VERIFY_ERROR. Проверка source=1 placeholders не выполняется. verify_and_purge_all останавливается на первом отказе; атомарность — по каналу, @@ -83,14 +99,15 @@ verify_and_purge_all останавливается на первом отказ start отклоняет запрос до создания Merkle-сессии, без done callback. Проверяются привязка node_id к X25519, доверенный Ed25519, подписи блока участника и владельца. -Для дерева приглашений родитель может прийти позже ребёнка; finish повторно проверяет зависимости -перед подтверждением корня. Это не отдельная карантинная таблица: промежуточные записи существуют в БД -до finish, поэтому MT_OK нельзя заменять фактом их присутствия. -finish проверяет имеющиеся ненулевые подписи непосредственных пригласивших; -отсутствующая зависимость допускает завершение сверки, но не допуск участника. -group_policy после сверки обходит цепочки от корней и рассчитывает admitted по текущим правам. -validate_pubkey и validate_peer проверяют наличие строки без фильтра source/deleted; -допуск CHAT-группы отдельно проверяет topo_node_sqlite_member_allowed. +Для дерева приглашений родитель может прийти позже ребёнка; commit_pull проверяет +целый полученный состав до публикации общих ключей. group_policy обходит цепочки от +корней и рассчитывает admitted по текущим правам. validate_peer требует живой CHAT-группы, +допуска self/peer и совпадения ключа участника с аутентифицированным ETCP. +validate_request разрешает лишь запрос к известному источнику с проверенным JOIN, +когда собственного допуска ещё нет. Источник самостоятельно проверяет право выдачи; +получатель не отдаёт хеши/записи в обратную сторону и проверяет результат после DONE. +validate_pubkey остаётся вспомогательной проверкой наличия опубликованной строки; +он не является разрешением на доступ. author_key требует source=0/deleted=0, доверенный ключ, join и сертификат непосредственного пригласившего. Возвращает ACTIVE, INACTIVE, PENDING, INVALID или ERROR; выходной ключ меняется только при ACTIVE. PENDING означает недостающий ключ/сертификат, а не отзыв членства или ошибку SQLite/OpenSSL.