|
|
|
@ -126,3 +126,37 @@ Wire-запись: message_id:32, node_id:8, kind:1, ver:8, data_len:2, data, si |
|
|
|
Членство проверяется через подписи дерева приглашений и join, привязывающий Ed25519 к узлу. |
|
|
|
Членство проверяется через подписи дерева приглашений и join, привязывающий Ed25519 к узлу. |
|
|
|
Слой feedback хранит подписанные байты независимо от наличия исходного сообщения; |
|
|
|
Слой feedback хранит подписанные байты независимо от наличия исходного сообщения; |
|
|
|
семантику выбранных пунктов и эмодзи проверяет вызывающий модуль до учёта результата. |
|
|
|
семантику выбранных пунктов и эмодзи проверяет вызывающий модуль до учёта результата. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Опросы и реакции |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`chat_poll_codec` задаёт общий каталог 16 эмодзи и канонические кодеки. |
|
|
|
|
|
|
|
Реакции: count:1 и отсортированные уникальные номера; максимум 8 реакций автора. |
|
|
|
|
|
|
|
Ответ: count:1, отсортированные уникальные номера пунктов, custom_len:2, UTF-8 текст. |
|
|
|
|
|
|
|
Пустой набор/ответ кодируется нулевой длиной. Собственный текст — максимум 1024 байта. |
|
|
|
|
|
|
|
Структурно неверные состояния не применяются; семантически неверные подписанные ответы |
|
|
|
|
|
|
|
сохраняются, но исключаются из подсчёта, чтобы порядок получения опроса не менял Merkle-корень. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Опрос — подписанное сообщение `content_type=poll`, data=`b64:` + URL-safe base64. |
|
|
|
|
|
|
|
Wire v1: version:1=1, mode:1 (single=1/multiple=2), allow_custom_answer:1, option_count:1, |
|
|
|
|
|
|
|
затем вопрос и варианты как length:2 + UTF-8. Числа big-endian, весь poll максимум 2048 байт. |
|
|
|
|
|
|
|
Вопрос — максимум 512 байт, 2–32 разных непустых варианта по 256 байт. |
|
|
|
|
|
|
|
Порядок вариантов неизменяем; номер варианта — индекс с нуля. |
|
|
|
|
|
|
|
single разрешает один вариант либо собственный текст, multiple — варианты и необязательный текст. |
|
|
|
|
|
|
|
Изменение ответа заменяет его целиком с ver+1; нулевой ответ отменяет голос. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
message_id сохраняется в msg_<channel> с UNIQUE-индексом: |
|
|
|
|
|
|
|
SHA256(`utun-chat-message-v1` || BE64(channel_id) || BE64(timestamp) || author_signature). |
|
|
|
|
|
|
|
Этот ID одинаков на всех узлах и возвращается API сообщений и результатом публикации опроса. |
|
|
|
|
|
|
|
Получение исходного сообщения повторно проверяет отложенные ответы. Пользовательские результаты |
|
|
|
|
|
|
|
вычисляются по последним допустимым непустым состояниям; проценты — от числа ответивших. |
|
|
|
|
|
|
|
При нескольких вариантах сумма процентов может превышать 100%. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Команды `poll_create`, `vote`, `react`, `feedback`, `reaction_catalog` разбираются единым |
|
|
|
|
|
|
|
chat_feedback_command в потоке ядра. Desktop и Android получают адресные события FEEDBACK_CHANGED |
|
|
|
|
|
|
|
и коррелированные результаты FEEDBACK_RESULT; GUI-поток не пишет подписанные данные. |
|
|
|
|
|
|
|
При старте чата запускается member_sync по известным онлайн-пирам, затем feedback sync: |
|
|
|
|
|
|
|
это нужно и при restart поверх сохранившегося UP-транспорта, когда нового conn_up не будет. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test_chat_poll проверяет пользовательский API, кодеки, ограничения, отмены и отложенный опрос. |
|
|
|
|
|
|
|
test_chat_poll_network проверяет A ↔ B ↔ C, собственный Unicode-ответ, реакцию и восстановление C |
|
|
|
|
|
|
|
после остановки чата без возвращения отменённых состояний. |
|
|
|
|