Реєстрація та обліковий запис

Чому не потрібні логін і пароль?

Під час реєстрації застосунок отримує від сервера невелике криптографічне завдання (Proof of Work) і розв’язує його — це захист від автоматичної реєстрації ботами. Паралельно генеруються унікальні ідентифікатори пристрою та кілька наборів ключів шифрування: довгострокові ключі ідентичності, підписані передключі й одноразові передключі (зокрема постквантові ML-KEM-1024). На сервер надходять лише публічні частини цих ключів і результат PoW-завдання. Приватні ключі ніколи не залишають пристрій. Пароля немає: обліковий запис визначають ключі, а повернути доступ до нього на новому пристрої можна ключем відновлення з 12 слів.

Чи можна вийти з облікового запису й увійти знову?

Так, за допомогою ключа відновлення з 12 слів: на новому пристрої або після перевстановлення виберіть «Відновити (Restore)» і введіть слова. Повернеться обліковий запис та його адреса; старі повідомлення й сесії залишаються на попередньому пристрої й не переносяться. Без цих слів втрата пристрою чи видалення застосунку означає втрату облікового запису назавжди.

Як не втратити обліковий запис під час зміни телефона?

Ключ відновлення створюється сам під час реєстрації — нічого робити не потрібно. Зберегти його копію (12 слів) можна пізніше, в Налаштуваннях (Settings): застосунок нагадає, а перед виходом з облікового запису попросить обов’язково. Доки копію не зроблено, слова зберігаються на пристрої зашифрованими й відкриваються лише після Face ID, відбитка пальця або коду розблокування телефона; після копіювання їх із пристрою стирають. Запишіть їх і зберігайте в надійному місці — у Konstruct немає вашого телефона й пошти, це єдиний спосіб повернути обліковий запис.

Контакти

Як комусь написати?

Система влаштована так, що незнайома людина не може просто почати вам писати. Щоб почати розмову, один ділиться QR-кодом або посиланням-запрошенням, а другий сканує його чи переходить за ним. Вони одноразові: QR-код діє п’ять хвилин, посилання — дванадцять годин, — прийняте одного разу посилання повторно використати не можна. Окремо ви можете ввімкнути в налаштуваннях виявлення й стати знайденим за іменем користувача; за замовчуванням воно вимкнене, тож доки ви його не ввімкнули, запрошення — єдиний шлях.

Навіщо таке обмеження? Це ж незручно.

Це навмисне рішення. У більшості месенджерів достатньо знати номер телефона чи нікнейм, щоб почати закидати людину повідомленнями. Тут взаємна згода вшита в архітектуру, а не просто задекларована в політиці.

Що буде, якщо хтось поділиться моїм QR-кодом без мого відома?

Код приймається лише один раз, тому за поширеним посиланням зможе додатися не більше однієї людини, а вже використане посилання нічого не зробить. Крім того, посилання перестає діяти через дванадцять годин після створення, а QR-код — через п’ять хвилин. Якщо хтось усе ж додався, ви побачите нову розмову й зможете одразу його заблокувати.

Шифрування та приватність

Як працює шифрування?

Усі повідомлення шифруються на пристрої відправника перед надсиланням і розшифровуються лише на пристрої отримувача. Сервер бачить лише зашифрований потік і маршрутизує його — прочитати вміст він не може. Для встановлення сесії використовується X3DH, розширений постквантовим узгодженням ключів (PQXDH): відправник інкапсулює секрет ML-KEM-1024 у Kyber-передключ отримувача, і цей секрет входить до початкового ключа сесії разом із класичними — саме це обмежує сценарій «записати зараз, розшифрувати квантовим комп’ютером пізніше». Постквантовий захист діє з першого повідомлення, а сесію без нього застосунок не встановить. Далі працює Double Ratchet, що змінює ключі з кожним повідомленням, — і в кожного повідомлення є ще й власний постквантовий ключ, — тож компрометація одного ключа не розкриває ні минулих, ні майбутніх повідомлень. Хто надіслав повідомлення, також приховано постквантово; дзвінки захищені постквантовим DTLS, коли його підтримують обидва застосунки. Поки класичні: підписи сервера (сертифікати відправника, журнал прозорості ключів), вхід пристрою й відновлення облікового запису, токени Privacy Pass і транспортний TLS; груп поки немає; повний список — у специфікації протоколу.

Що саме бачить сервер?

Дуже мало, і ніщо з цього — не ви. Щоб доставити повідомлення, серверу потрібні непрозорий ідентифікатор облікового запису отримувача, розмір шифротексту й час отримання; ще він зберігає ваші публічні ключі та, на iOS, push-токен. Це весь список. Він не бачить ні вмісту, ні вашого імені, ні аватара, ні списку контактів — і, на постійно ввімкненому шляху захисту відправника (sealed sender), не бачить, хто надіслав повідомлення. Повідомлення лежать на сервері лише зашифрованими й видаляються за терміном зберігання (близько 7 днів), а не в момент доставки. Ім’я користувача необов’язкове, у маршрутизації не бере участі й зберігається лише як ключований хеш заради одного завдання — щоб вас могли знайти; сам пошук вимкнений, доки ви не ввімкнете виявлення, тож за замовчуванням обліковий запис узагалі не можна знайти за іменем.

А метадані? Хто з ким спілкується?

Це складніша частина. Сервер усе ще бачить, що хтось доставив шифротекст пристрою B (отримувач, час, розмір). За постійно ввімкненого захисту відправника (sealed sender) він не дізнається, хто саме написав, — див. наступне запитання. Захист від блокувань частково приховує мережевий шлях. Повна анонімність на рівні маршрутизації (сховатися і від отримувача, і від кореляції за IP та таймінгами) — завдання іншого порядку, і сьогодні воно не розв’язане.

Чи знає сервер, хто надіслав повідомлення?

Ні — поле відправника не кладеться в конверт, і це завжди ввімкнено для звичайного трафіку (повідомлення, квитанції про доставку, встановлення дзвінка, обмін профілями). Перемикача, який можна забути, немає. Ваш пристрій запечатує підписаний сертифікат відправника на ключ отримувача: отримувач може його відкрити й перевірити, хто написав, а сервер — ні. Кілька внутрішніх шляхів — підтримання з’єднання, синхронізація ваших власних пристроїв, службові повідомлення сесії — за задумом і далі несуть відправника.

Варто уточнити, що саме приховується, бо це не особа. Її в сервера ніколи й не було: обліковий запис тут — це пара ключів і непрозорий ідентифікатор, без номера телефона, пошти та справжнього імені, тож зіставляти з людиною спочатку нічого. Захист відправника прибирає останній зв’язок між двома такими ідентифікаторами — хто кому писав. Мережевий рівень — окрема розмова, він вищий: час і IP залишаються видимими, і саме там працює спостерігач із ресурсами.

Обмеження: захист відправника (sealed sender) приховує від сервера його особу, але не час, розмір чи IP — це видно на мережевому/транспортному рівні. Токени Privacy Pass можуть надходити разом із sealed-надсиланням для антиспаму; server-side enforcement ще розгортається — rate-control на токенах поки доопрацьовується й не завершений.

Ви збираєте аналітику чи телеметрію?

Ні — взагалі. Жодної аналітики, метрик використання, поведінкових подій, надсилання крашів, рекламних ідентифікаторів. Не «зібрано й знеособлено» — не зібрано взагалі. У застосунку немає сторонніх трекерів (ні Firebase, ні Crashlytics, ні Sentry, ні Amplitude, ні Segment); єдині зовнішні залежності — транспорт/медіа та, на iOS, локальна бібліотека розпізнавання мовлення. Релізні збірки до того ж не записують діагностичних журналів на диск і не мають екрана налагодження чи експорту журналів. Коли нам потрібні журнали, щоб виправити помилку, їх надсилаєте ви кнопкою «поділитися» в бета-збірці — жодного тихого надсилання.

Профіль

Навіщо потрібен Display Name?

Ваше відображуване ім’я та аватар живуть на пристрої; вони не є частиною публічного профілю, і знайти їх ніхто не може. Коли ви починаєте нову розмову, співрозмовник бачить лише згенерований псевдонім — детермінований, для певного ID завжди той самий. Щоб показати справжнє ім’я та фото, відкрийте профіль співрозмовника й увімкніть «Поділитися моїм профілем» (Share my profile): і те, й інше піде зашифрованим каналом. Один виняток: під час надсилання запиту в контакти до нього додаються ваше ім’я користувача та відображуване ім’я, щоб отримувач розумів, хто просить. Сервер зберігає цей знімок зашифрованим, але під власним ключем — це не наскрізне шифрування; аватар до знімка не входить ніколи.

Чому згенероване ім’я, а не просто порожнє?

Порожнє ім’я незручне: у списку чатів ви бачили б безлики рядки й не могли б відрізнити один контакт від іншого. Згенероване ім’я стабільне — «Швидкий Сокіл» завжди залишатиметься «Швидким Соколом» для цього ID, на будь-якому пристрої.

Якщо в користувача задано username, я його бачу?

Так. Пріоритет відображення: Display Name (якщо поділився) → username → згенероване ім’я. Якщо людина зареєструвалася з username @john, ви побачите саме його, а не «Мирний Кит».

Повідомлення

Що означають статуси повідомлень?
  • Надсилається (Sending) шифрується на вашому пристрої
  • Надіслано (Sent) пішло з пристрою, сервер його прийняв
  • Доставлено (Delivered) пристрій отримувача розшифрував його й надіслав підтвердження
  • У черзі (Queued) ще не пішло — застосунок і далі пробує сам; натисніть, якщо не хочете чекати
  • Не надіслано (Failed to send) відхилено з причини, яку повтор не усуне, тому саме нічого не станеться; натисніть, щоб спробувати знову

Статусу «прочитано» немає, і це зроблено навмисно: позначка про прочитання повідомила б відправнику, коли ви відкрили застосунок, — факт про вас, який повідомленню не потрібен. «Доставлено (Delivered)» — це зашифрована квитанція від пристрою отримувача, а не повідомлення сервера про те, що він щось переслав.

Чи можна редагувати надіслані повідомлення?

Так, редагування підтримується. Після зміни повідомлення отримує позначку «змінено (edited)». Редагування поширюється на пристрій отримувача через той самий механізм доставки, що й звичайні повідомлення.

Чому іноді не надходять сповіщення, коли застосунок закрито?

На iOS сповіщення надходять через Apple Push Notification Service (APNs): потрібен стабільний інтернет, і якщо телефон у режимі польоту, за VPN з агресивним фільтруванням або Apple вважає push-сповіщення «низькопріоритетним», сповіщення може затриматися або не надійти. На Android push-сервісів узагалі немає: застосунок тримає власне з’єднання, про що свідчить постійне сповіщення; агресивна економія батареї або заблокована мережа можуть затримати повідомлення. Коли застосунок знову відкриється, повідомлення підтягнуться автоматично.

Захист від блокувань

Чи працює Konstruct там, де месенджери блокують?

У застосунку є режим захисту від блокувань (Censorship protection): він змінює те, як застосунок виходить у мережу, коли пряме з’єднання блокується. У налаштуваннях це один перемикач на три положення — вимкнено, автоматично, увімкнено, — і за замовчуванням стоїть «автоматично»: поки пряме з’єднання працює, використовується воно, перемикання відбувається лише після доведеної відмови. Налаштовувати нічого, адреси вводити не потрібно, усе відбувається у фоні. Реалізація відкрита, тож дизайн може вивчити будь-хто.

Чи захист від блокувань завжди ввімкнений?

За замовчуванням — автоматично: пряме з’єднання швидше, тому поки воно працює, використовується воно, а перемикання відбувається лише за доведеної відмови. Можна також примусово ввімкнути або вимкнути. Чого ми свідомо не публікуємо — які саме техніки зараз у строю і де вони зараз проходять або не проходять: публічне й актуальне зведення з цього питання — безкоштовний зворотний зв’язок для тих, хто блокує. З тієї самої причини цього не показує й сам застосунок.

Стійкість мережі та життєздатність

Що буде, якщо сервери Konstruct вимкнуться?

Обмін повідомленнями зупиняється до його повернення. Альфа працює на одному довіреному сервері, і другого шляху сьогодні немає — ні ретрансляторів, ні прямих з’єднань, ні іншого вузла, на який можна спертися. Усе зашифроване залишається зашифрованим, нічого не губиться — просто не рухається. Дорожня карта існує саме для того, щоб це перестало бути правдою, і нічого з неї поки не випущено.

Базовий обмін повідомленнями завжди буде безкоштовним?

Так — безумовно. Надсилання повідомлень, отримання повідомлень, E2EE та всі функції безпеки ніколи не опиняться за платним бар’єром. Модель лише на донатах історично виявилася крихкою для проєктів, що дбають про приватність, тому Konstruct планує поєднання: добровільні пожертви, опційні преміумфункції (більші файли, розширена історія, теми — ніколи не функції безпеки) і B2B-хостинг для організацій. Ядро завжди буде безкоштовним.

З чого живе Konstruct? Чи можна задонатити?

Без реклами, без перепродажу даних, без телеметрії — зворотний бік у тому, що Konstruct живе на добровільних донатах. Вони йдуть безпосередньо на розробку та сервер. Якщо цінуєте приватність — віддайте перевагу Monero (XMR): на відміну від біткоїна, його ланцюжок не публічний. Перед надсиланням завжди звіряйте адресу з репозиторієм проєкту на випадок підміни сторінки.

  • Monero (XMR) — рекомендовано:
    496i5qvPzRtJPQjiPXnLvEGutjHFth4pWDQaJwbbMreyaTYg4qfbo48MXrTnYH32MHiAn5GcSEN1c48EYBvVkrx9Pi5BWvn
  • Bitcoin (BTC):
    bc1q5cthgu6k9utg9hk2mx2xshdtsrhvu54ysmqhmm
  • Ko-fi — зручно, але не приватно: платіжний сервіс знає, хто ви:
    ko-fi.com/construct_msg
Що таке P2P-режим і коли він активується?

Режим P2P запланований, але ще не реалізований — увесь трафік зараз іде через центральний сервер. Цільовий задум: коли обоє співрозмовників одночасно онлайн і підключені до сервера Konstruct, сервер подасть їм сигнал перейти на пряме P2P-з’єднання поверх QUIC. Після встановлення з’єднання сервер зникає зі шляху доставки — трафік іде напряму між пристроями. Якщо одна зі сторін виходить офлайн, доставка повертається на сервер.

Безпека та захист

Що, якщо мені почнуть масово писати незнайомі люди?

Для цього в застосунку є «Режим захисту» (Lockdown mode). Коли його ввімкнено, сповіщення приходять лише від людей, які були у ваших контактах на момент його активації. Повідомлення від нових відправників усе одно зберігаються — вони просто вас не турбуватимуть. Режим корисний, якщо ви публічна людина й хочете тимчасово закритися від нових контактів.

А якщо одна конкретна людина почне спамити сотнями повідомлень?

Якщо від одного відправника за короткий час приходить підозріло багато повідомлень (понад ~10 за 30 секунд), клієнт автоматично покаже попередження й заглушить сповіщення від нього. Ви зможете або дозволити його, або заблокувати. Важливо: це захист на боці отримувача, і він працює незалежно від того, яким клієнтом користується відправник.

Технічні питання

Що таке «сесія» і чому вона іноді «ламається»?

Сесія — це встановлений зашифрований канал між двома пристроями. Вона будується на одноразових ключах, які не можна використовувати повторно, і ключі змінюються з кожним повідомленням. Якщо застосунок довго не працював, пристрій перевстановили або співрозмовник видалив чат, вхідне повідомлення може виявитися нечитабельним. Тоді застосунок отримувача повідомляє відправникові, на якому стані сесії було написано це повідомлення; застосунок відправника відкриває новий стан і надсилає повідомлення ще раз. Користувач, як правило, нічого не помічає — повідомлення просто приходить.

Чи підтримується кілька пристроїв?

Прив’язати другий пристрій у публічних збірках поки що не можна. Нативний десктопний клієнт заморожено, у розробці — консольний (TUI). Оскільки ідентичність прив’язана до ключів, а не до облікового запису на сервері, підтримка кількох пристроїв потребує окремого механізму прив’язки ключів — над цим працюємо.

Який транспорт у Konstruct для live-повідомлень?

Live-повідомлення йдуть через двонапрямлений gRPC MessageStream — один довгоживучий потік для heartbeat-пакетів, вхідних повідомлень і receipt-квитанцій, без request/response polling. В актуальних збірках для iOS основний шлях — QUIC (construct-transport); якщо QUIC ріжуть або handshake не проходить, клієнт автоматично переходить на gRPC поверх HTTP/2 + TLS 1.3. Наскрізне шифрування не залежить від транспорту: дротом їде лише sealed ciphertext.

Для тестувальників

Що перевіряти в першу чергу?
  • Реєстрація та додавання контакту через QR-код
  • Надсилання й отримання повідомлень (в обидва боки)
  • Статуси доставки — чи доходить повідомлення до «доставлено» (Delivered), і чи повторюється надсилання для «у черзі» та «не надіслано» (Failed to send) після натискання?
  • Редагування повідомлень — чи бачить отримувач зміни?
  • Сповіщення при згорнутому застосунку
  • Поведінка за поганого зв’язку (авіарежим → відновлення)
  • Відновлення облікового запису за ключем відновлення після перевстановлення
  • Копія ключа відновлення з Налаштувань (Settings)
Як повідомити про баг?

У діагностичних (внутрішніх) збірках шлях такий: Налаштування (Settings) → Діагностика та журнали (Diagnostics & logs) → Поділитися журналами (Share logs). Публічні збірки журналів не ведуть і цей екран взагалі не компілюють — якщо у вашій збірці такого рядка немає, опишіть сценарій, і ми видамо вам діагностичну збірку. Чим точніший опис (що робили, чого очікували, що сталося), тим швидше ми розберемося. Для проблеми із сесією додайте журнали з обох пристроїв.

Чому в журналах так багато рядків, що повторюються?

У налагоджувальних збірках деякі компоненти пишуть у журнал при кожному оновленні інтерфейсу — для розробки це нормально. Рядки на кшталт FRC updated: 69 message(s) in window — це оновлення списку чатів, вони не означають проблеми.