← Все проекты

Активная разработка · web доступен AirChat

Переписка, ключ от которой остаётся у вас

Мессенджер без номера телефона и регистрации. Ваша seed-фраза — ваш аккаунт: одна идентичность открывает зашифрованную историю на другом устройстве.

Моя роль

Логика продукта, модель аккаунта и архитектура

Этап / дата

Текущее состояние: сентябрь 2026

Формат разработки

Логика и архитектура — мои решения. Код создаётся с AI-инструментами.

Задача и мой вклад

Смена телефона часто означает зависимость от номера, оператора аккаунта или отдельного резервного архива. Задача — дать человеку переносимый аккаунт и синхронизацию, не передавая серверу ключи от содержимого.

Мой вклад. Я определяю поведение аккаунта и восстановления, пользовательские сценарии, границы доверия между клиентом и сервером и конструкцию синхронизации. Отвечаю за то, чтобы техническая модель оставалась понятной человеку: что защищено, что видно серверу и что происходит при потере ключа.

Идентичность выводится из seed-фразы. Клиент шифрует записи до отправки, а сервер хранит зашифрованные сущности с ревизиями и курсорами. Локальная база служит проекцией для интерфейса. WebRTC-сигналинг отделён от хранения истории.

Что получилось

Доступен браузерный клиент. В исходниках реализованы переносимая идентичность, зашифрованная синхронизация аккаунта, ревизии, удаление через tombstone и проверка принадлежности профилю. Нативные сборки дополняют web локальным LAN-обменом. Демо ниже показывает реальный экран входа, а не испытание всей криптографической модели.

Инженерные решения

Повтор запроса без повтора изменения

Идемпотентные мутации и курсоры позволяют повторно доставить данные после обрыва связи. Подписанный запрос и его nonce решают отдельную задачу — защиту от повторного воспроизведения.

Удаление тоже синхронизируется

Tombstone сохраняет факт удаления. Иначе другой клиент может загрузить старую запись и вернуть уже удалённое сообщение.

История и соединение — разные сервисы

Сигналинг помогает установить связь между устройствами. Он не становится второй базой сообщений.

Архитектура

Устройство A · ключ
Устройство B · ключ
↓ одна seed-идентичность
Шифрование на клиенте
↓ подписанные запросы
Sync API · ciphertext + cursor
↓ pull → расшифровать → применить
Локальная проекция
Отдельный WebRTC-сигналинг
Слой Технологии и назначение
Frontend React Native, Expo 55, TypeScript; web и нативные клиенты
Backend Node.js, cloud-vault / sync, отдельный WebRTC-сигналинг
Данные SQLite на клиенте; зашифрованные сущности, ревизии и курсоры на сервере
Безопасность BIP39, did:key, @noble; ключи и шифрование на клиенте

Компромиссы и выводы

Восстановление через seed-фразу убирает зависимость от номера телефона, но потерю фразы нельзя исправить сбросом пароля у оператора. Зашифрованные данные скрывают содержимое, но не все метаданные соединения и синхронизации.

Что показала практика

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

Что бы я улучшил сейчас

Сейчас я бы прежде всего расширил воспроизводимые проверки на двух устройствах: конкурирующие изменения, удаление во время офлайна, восстановление и отзыв устройства. Результаты таких прогонов полезнее общего обещания «безопасного мессенджера».

Эксплуатация и данные

Синхронизация, сигналинг и уведомления разделены на самостоятельные сервисы. В исходниках предусмотрены scrubber логов и Sentry. Запуск нативного клиента требует соответствующей сборки и платформенных зависимостей; web имеет собственные ограничения.

Данные и миграции

У мутации есть идентификатор, ревизия, владелец и признак удаления. sync_entity_heads хранит локальные версии, sync_state — курсор и состояние синхронизации. Схема применяется на стороне соответствующего сервиса; это не одна общая база для всех клиентов.

Сущность Что хранится
Мутация idempotency key, revision, owner, tombstone
sync_entity_heads Локальная версия синхронизируемой записи
sync_state epoch, pull cursor, timestamps
Медиа Зашифрованные байты + ссылка; ключ у клиента

Ограничения

Сервер видит метаданные. Посты по публичной ссылке не зашифрованы. Защита ключей в браузере слабее нативного secure storage. Для синхронизации и звонков нужна связь. Независимый аудит криптографической системы здесь не заявляется.

Проверяемые источники

Проверено 24.09.2026: 71 проверка sync/vault-сервиса; локальный /health отвечает. Это целевая проверка описанных решений, не аудит всего приложения.

Утверждения выше связаны с публичным кодом и документацией. Ссылки закреплены за проверенной версией; статус CI по ссылке может меняться.

CI / checks · MIT licence · Запуск проекта

Есть задача или идея?

Давайте обсудим.

Проект, партнёрство или сильная команда — открыт к разговору.