# Triad: короткие сообщения при перебоях связи

Исследование и проектное предложение, 25 сентября 2026 года. Реализация не выполнена этим документом; Site не изменялся.

**Предлагаемое ядро — зашифрованные переносимые капсулы сообщений, которые можно сохранить, перенести и передать позже без обязательного центрального координатора.** Это дополнительный канал связи для знакомых контактов. Он не создаёт радиосвязь там, где нет физического канала, и не обещает доставку за фиксированное время.

Подход соответствует идее delay-tolerant store–carry–forward: отправитель и получатель могут появляться в сети в разное время; капсулу переносит посредник. RFC 9171 описывает такую архитектуру и отдельно отмечает, что сам Bundle Protocol не гарантирует доставку. Наш JSON/бинарный MVP нельзя называть совместимым BPv7 без реализации его формата и процедур. [RFC 9171](https://www.rfc-editor.org/rfc/rfc9171.html)

## Минимальный полезный продукт

1. **Постоянная локальная идентичность.** Приложение создаёт отдельные ключи подписи и шифрования; отпечаток публичной идентичности остаётся тем же после перезагрузки. Хранение CryptoKey в IndexedDB предусмотрено WebCrypto. Не генерировать незаметно новую идентичность после ошибки чтения: показать потерю ключа и явное создание нового профиля. [WebCrypto](https://www.w3.org/TR/webcrypto/)
2. **Ручной обмен контактами.** Карточка содержит версию, оба публичных ключа и отпечаток. Обмен файлом/QR или проверенным каналом; сверка отпечатка лично. Имя — пользовательская подпись контакта, не удостоверение личности. Ключ, пришедший внутри сообщения, не заменяет уже закреплённый ключ. Изменение контакта требует отдельного действия.
3. **Капсула не зависит от транспорта.** Экспорт `.triad`/импорт файла — обязательный путь. Копирование текста — запасной путь. Передачу файла через AirDrop/мессенджер/носитель выполняет пользователь средствами устройства; браузер не управляет ими автоматически. QR сначала использовать для контактной карточки: полноценная капсула может потребовать нескольких кадров.
4. **Локальные входящие, исходящие и очередь пересылки.** Сообщения хранятся до появления способа передачи. Посредник принимает и экспортирует только шифротекст, не получает ключ расшифрования. Удаление и участие в пересылке контролирует владелец устройства. Несколько независимых копий допускаются без голосования и выбора главного сервера.
5. **Офлайн-оболочка.** После успешной предварительной загрузки и установки Service Worker интерфейс, код, шрифты и импорт/экспорт работают без backend. Индикатор «Готово к офлайн-работе» появляется только после успешного precache и активации. Первый визит к ещё не загруженному приложению без связи невозможен. Service Worker требует secure context (обычно HTTPS), может завершаться браузером и не является постоянно работающим ретранслятором. [Service Workers](https://www.w3.org/TR/service-workers/)

## Формат и минимальные защитные свойства

Рекомендуемые **проектные**, а не стандартные лимиты: plaintext до 2 КиБ UTF-8, одна капсула до 16 КиБ, пакет импорта до 100 капсул/2 МиБ, срок жизни до 7 суток. Проверять длину до разбора и до дорогой криптографии; очередь ограничивать по байтам и количеству.

Аутентифицированные поля: `protocol/version`, криптографический набор, случайный `messageId`, отпечатки отправителя и адресата, время создания/истечения, тип `message|receipt`, материал инкапсуляции, nonce и ciphertext. Подпись связывает канонические байты заголовка и шифротекста; AEAD связывает тот же неизменяемый контекст. Сообщение шифруется для конкретного адресата, а не общим ключом всех ретрансляторов.

Предпочесть проверенную реализацию стандартной конструкции, например HPKE плюс отдельную аутентификацию отправителя, с фиксированным набором алгоритмов и тест-векторами. HPKE сам по себе не задаёт формат приложения, доверие контактам, защиту от повторов и интерфейс квитанций. Если MVP использует собственную композицию WebCrypto ECDH/HKDF/AES-GCM/ECDSA, обозначить её экспериментальной до независимой проверки и не называть реализацией HPKE без соответствия RFC. [RFC 9180](https://www.rfc-editor.org/rfc/rfc9180.html)

Для подписи и дедупликации использовать неизменяемые байты/хеш содержимого, а не перегенерируемый JSON и не ECDSA-подпись как ID. Метки маршрута хранить отдельно. Неверная подпись не должна занимать место настоящего ID или изменять состояние replay protection. Получатель атомарно записывает принятие и его ID в IndexedDB; повтор не создаёт второе входящее. Квитанцию на повтор допустимо повторно экспортировать с ограничением частоты.

Время устройства может ошибаться: показывать проблему часов, не менять подписанное время при ретрансляции. TTL ограничивает обработку честным клиентом, но не стирает чужие копии. Hop count также не останавливает злонамеренного посредника, способного копировать пакет; реальные местные ограничения — квоты, дедупликация, размер и согласие владельца.

## Копия у посредника и получение адресатом — разные события

| Состояние | Что действительно известно |
|---|---|
| Сохранено локально | Локальная транзакция завершена |
| Экспортировано | Создан файл/текст; его мог никто не получить |
| Посредник заявил о копии | Это заявление посредника, даже если подписанное |
| Подтверждено адресатом | Проверена квитанция от закреплённого ключа адресата, связанная с хешем исходной капсулы |
| Прочитано человеком | Не следует из предыдущих статусов; отдельное добровольное действие, если функция вообще нужна |

Квитанция — маленькая подписанная капсула, желательно зашифрованная обратно отправителю, содержащая digest исходной капсулы и тип принятия. Создавать после проверки, расшифровки и успешного локального сохранения. Подпись доказывает утверждение держателя ключа, а не вечное хранение или человеческое понимание. Потерянная квитанция означает «нет подтверждения», а не доказанную недоставку. Нельзя удалить последнюю исходящую копию только потому, что посредник ответил HTTP 200.

## Реальные пределы защиты

При сохранности ключей и проверенных контактах даже большинство вредоносных ретрансляторов не должно расшифровывать адресованные другим сообщения или подделывать принимаемые сообщения/квитанции. Однако они могут задерживать, удалять, дублировать пакеты и анализировать доступные метаданные. Доставка требует хотя бы одной последовательности реально состоявшихся передач через добросовестных переносчиков либо прямого контакта. «66,6% злоумышленников» не является общей гарантией доступности. RFC 9172 также разделяет конфиденциальность содержимого и видимость самого защищённого обмена. [BPSec](https://www.rfc-editor.org/rfc/rfc9172.html)

Идентификаторы адресатов, размеры и моменты передачи могут раскрывать связи; не обещать анонимность. Статический ключ расшифрования без ratchet не обеспечивает защиту старых сообщений после кражи этого ключа. Неизвлекаемый CryptoKey не защищает от вредоносного JavaScript того же origin: он может попросить браузер расшифровать данные. Остаётся доверие к первоначальной поставке приложения и обновлениям; офлайн-кеш не решает проблему компрометации издателя.

Запросить `navigator.storage.persist()` и показывать результат. Обычное best-effort хранилище может быть очищено; persistence зависит от разрешения и не защищает от удаления пользователем. Ключи и очереди привязаны к origin: открытие другого зеркала не переносит их автоматически. Для MVP честно указать отсутствие восстановления при потере профиля; позже — отдельный проверенный зашифрованный recovery/export, без пересылки открытых приватных ключей. [WHATWG Storage](https://storage.spec.whatwg.org/)

## Дальнейшие транспортные адаптеры

Следующий слой — несколько независимых почтовых шлюзов на компьютерах/мини-ПК с дисковой очередью и резервным питанием. Они хранят зашифрованные капсулы, принимают загрузку/выгрузку по доступному каналу, работают по локальным квотам и не владеют идентичностями пользователей. Список шлюзов можно обменять вручную; отключение каталога не лишает доступа к уже известным адресам.

Затем нативные клиенты: Android Wi-Fi Aware/Direct и Apple Network framework/Wi-Fi Aware на поддерживаемых моделях, с разрешениями и проверкой реального сочетания устройств. Это отдельная разработка, а не возможность уже существующего браузерного MVP. Android документирует прямые Wi-Fi Aware соединения без точки доступа и необходимость проверки поддержки; Apple показывает отдельный нативный Wi-Fi Aware framework. [Android](https://developer.android.com/develop/connectivity/wifi/wifi-aware), [Apple](https://developer.apple.com/videos/play/wwdc2025/228/)

Briar — полезный действующий ориентир: независимая синхронизация устройств, локальные каналы и отдельный mailbox при несовпадающем времени подключения. Это подтверждает класс решения, но не защищённость Triad и не взаимную совместимость протоколов. [Briar](https://briarproject.org/how-it-works/)

## Проверки MVP и модель внедрения

Обязательный демонстрационный сценарий: три независимых браузерных профиля A → посредник → B; backend недоступен, капсула переносится файлом, посредник не расшифровывает текст, B выдаёт квитанцию, A проверяет её после обратного переноса. Затем reload/offline reload; сохранность идентичности и очереди; подмена каждого подписанного поля; ложная квитанция; другой адресат; повторы; повреждённый/слишком большой файл; неправильные часы; отказ persistence/переполнение; перезапуск между сохранением входящего и созданием квитанции. Все статусы должны отражать именно проверенное событие.

Первый пилот — добровольная небольшая группа жильцов/волонтёров, несколько шлюзов у независимых владельцев и регулярное упражнение с отключённым backend. Измерять долю сообщений с квитанцией, задержку, расход батареи, число ручных действий и потерю очереди. Не позиционировать MVP как гарантированный канал экстренной помощи.

Предлагаемая модель: бесплатный базовый локальный обмен и открытый формат; сообщество поддерживает перенос и шлюзы. Платный продукт для организаций — поставка и обслуживание шлюзов, резервное питание, настройка, обучение и поддержка. Платить за проверяемую эксплуатационную услугу, а не за число пересланных копий: иначе появится стимул создавать спам и поддельную активность. Выручку и экономику подтвердить оплачиваемым пилотом, не токеном и не размером заявленной сети.
