Ycontacts

Приватність і дані

Що зберігається, що зашифровано і що зникає назавжди — конкретно, без загальних слів.

Коротко

  • Телефони, пошти, соцмережі, адреса, примітка, день народження і текст розпізнаної візитки зашифровані в базі ключем вашого акаунта.
  • Ім'я, по батькові, альтернативне написання, компанія, посада і позначка «звідки контакт» шифруються так само: застосунок пише і читає їх лише зашифрованими. Але за замовчуванням ключ від шифру лежить на нашому сервері — технічно ми можемо розшифрувати ваші дані. Тому ми не кажемо «ми не бачимо ваших контактів»: це було б неправдою. Наскрізне шифрування, за якого ключ виводиться з вашого секрету і не залишає ваш пристрій, вмикається окремо — в налаштуваннях, у розділі «Безпека»; межі, які лишаються навіть із ним, перелічені нижче.
  • Фото візитки їде на розпізнавання до Cloudflare Workers AI. Cloudflare прямо зобов'язується в умовах не використовувати вміст клієнтів для тренування моделей — це записана обіцянка постачальника, а не наше прохання до нього. Щойно контакт створено, оригінал скану видаляється зі сховища.
  • Видалення акаунта прибирає все одразу: контакти, фото, ключі. Ніякої заморозки на 30 днів.
  • Замок екрана ховає застосунок, коли ви відійшли. Поки наскрізне шифрування вимкнене, він не шифрує дані у вкладці; з увімкненим — скидає ключі вкладки, тож після розблокування знадобиться ваш секрет.

Межі, які ми називаємо вголос

  • Фото не шифруються — ні аватари контактів, ні знімки візиток. Зашифровані ПОЛЯ контакту, а зображення лежать у файловому сховищі як є, тож ми технічно можемо їх відкрити. Це свідоме рішення, а не недогляд: шифрування фото коштує браузерного кешу і швидкого повторного показу. Чи змінювати це — окреме рішення, і поки воно не ухвалене, межа саме така.
  • Фото візитки їде до моделі розпізнавання відкритим — інакше вона нічого не прочитає. Це так і з увімкненим наскрізним шифруванням: інакше сканування не працює взагалі. Зате сам розпізнаний текст із візитки більше не осідає в нас: з увімкненим шифруванням колонка, у якій він лежав, не заповнюється зовсім.
  • Код застосунку віддає той самий сервер. Шифрування в браузері захищає від читання даних у базі, а не від сервера, який захотів би віддати змінений код. Це фундаментальна межа браузерного шифрування, і її визнають усі, включно з Proton. Тому наша обіцянка звучить інакше: ключ виводиться з вашого секрету, не залишає ваш пристрій, і ми його не зберігаємо.
  • Коли базу відкривають ключем відновлення, ми це бачимо і надсилаємо вам лист: щоб увійти таким способом, браузер мусить попросити в нас окремий фрагмент даних, і сам цей запит є подією. Межа в тому, що фрагмент, збережений на пристрої раніше, відкриє базу ще раз уже без звернення до нас — і такий вхід лишиться непоміченим. Тому ми ніде його не зберігаємо, а використаний ключ відновлення застосунок вимагає замінити.
  • Перші сім днів після вмикання — пільгове вікно: копія ключа ще лежить у нас, щоб повернути вам доступ, якщо секрет загубиться в перші дні. Поки вікно відкрите, наскрізного шифрування немає, і ми кажемо це прямо, з датою закриття, на екрані «Безпека». Сім днів — це найраніший строк, а не найпізніший: нашу копію ключа щоденне прибирання стирає лише в того, хто підтвердив розблокування. Без підтвердження вона лишається в нас довше — і через 30 днів після вмикання шифрування вимикається само: ключ знову під нашою охороною, а ми пишемо вам про це листом.
  • Межа, про яку варто знати: уже зняту копію бази не лікує ніщо. Ключ даних оновлюється при першому вході після закриття пільгового вікна, після зміни фрази і за кнопкою «Оновити ключ даних» у розділі «Безпека». Доки його не оновлено, ключ зі знятої копії відкриває і пізніші копії бази; після оновлення збиток обмежений зрізом на дату копії — контактів, доданих чи змінених пізніше, вона не відкриває. Те саме стосується телефонів і пошт: сліпий індекс виводиться з того самого ключа, тож ключ зі знятої копії дає відновити їх перебором за хвилини. Кожне оновлення ключа даних перераховує індекси новим ключем, тому для контактів, доданих чи змінених після оновлення, стара копія цього вже не дає.
Як це працює

Шифрування: AES-256-GCM за конвертною схемою. У кожного акаунта свій ключ даних (DEK), загорнутий серверним ключем (KEK); додаткові автентифіковані дані прив'язують шифротекст до конкретного поля конкретного запису, тож переставити значення місцями не вийде. Так влаштований акаунт за замовчуванням, і це НЕ наскрізне шифрування: сервер має доступ до KEK і технічно може розшифрувати дані. Шифрування в обох режимах ховає зміст, а не довжину: з копії бази видно, наскільки довге кожне значення.

Наскрізне шифрування (вмикається в налаштуваннях → «Безпека»): ключ даних загортається ключем, який виводиться з вашого секрету через Argon2id просто у браузері, а серверна обгортка видаляється. Вмикання міняє лише те, чим загорнутий ключ даних; сам ключ оновлюється окремо — при першому вході після пільгового вікна, після зміни фрази і за кнопкою в розділі «Безпека». Ні секрет, ні виведений з нього ключ на сервер не йдуть. Забутий секрет разом із втраченим ключем відновлення означають втрачені дані: якби ми могли їх повернути, ми могли б і читати.

Відкритим текстом лишаються службові дані, а не зміст контакту: статус запису, походження (створений вручну, з фото чи з файлу), назви ваших таблиць і груп, дати створення і зміни, посилання на файл фото, тип каналу і підпис до нього («робочий», «особистий»), назва мережі, у якій профіль, — але не сам профіль. Відкрита і ваша власна пошта, якою ви входите. Відкритими лежать і токени доступу до вашого Google-акаунта, якщо ви входите через Google: контакти ми шифруємо, а їх — ні, і це визнана межа, а не недогляд. Зашифровані: ім'я, по батькові, альтернативне написання, компанія, посада, «звідки контакт», телефони (разом із нормалізованим E.164), пошти, соцмережі, адреса, примітка, день народження, «де познайомились» і сирий текст скану. Старі відкриті колонки шести полів, зашифрованих останніми, фізично видалені з бази міграцією 0014 — у копії бази їх більше немає.

Пошук по телефону і пошті працює через сліпий індекс: HMAC-SHA256 на ключі, похідному від вашого DEK через HKDF, від результату лишаються перші 16 байтів. Індекс дозволяє знайти збіг, але відновити з нього номер чи адресу не можна.

Розпізнавання візитки: Cloudflare Workers AI (модель Mistral Small 3.1). Обрано саме його через приватність: в умовах Cloudflare прямо сказано, що вміст клієнтів не йде на тренування моделей. Раніше тут стояв Google Gemini через Vercel AI Gateway із прапорцем «не використовувати для навчання» — і це було лише проханням у запиті, тобто слабша гарантія; 2026-09-08 ми від нього відмовились. Фото не зберігається у провайдера: воно передається в запиті й видаляється з нашого сховища одразу після створення контакту.

Хто ще обробляє дані: Vercel (хостинг і сховище файлів), Neon (база даних), Cloudflare Workers AI (розпізнавання візиток), Resend (листи про скидання пароля).

Дані живуть, доки живий акаунт. Окремих архівних копій ми не тримаємо — резервне копіювання роблять Neon і Vercel у межах своїх сервісів. Нікому, крім названих вище, дані не передаються.

Кошик: видалений контакт лежить 30 днів і його можна відновити. Далі щоденне прибирання видаляє і рядок, і фото остаточно.

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

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

Код і його вивезення: сторінки віддаються з політикою безпеки вмісту (CSP). Вона закриває звичні канали, якими підмінена залежність винесла б ваш секрет: запити на чужі адреси (fetch, XHR, WebSocket, EventSource, sendBeacon), картинку-маячок, сабміт форми на чужий домен, чужий iframe і WebRTC у браузерах на Chromium. Чого вона НЕ закриває: верхньорівневої навігації — переходу на чужу адресу, у якій секрет їде частиною самого посилання. Цього не вміє жодна директива CSP, бо ту, що мала це вміти, прибрали з чернетки стандарту. Отже CSP ускладнює вивезення, а не унеможливлює його. З тієї ж чесності: script-src тримає 'unsafe-inline', бо фреймворк кладе інлайнові скрипти сам, — тобто чужий код, який уже потрапив у збірку, виконається.

Журнали: технічні логи Vercel і Neon містять адреси запитів, коди відповідей і час; змісту контактів у них немає. При кожному вході бібліотека автентифікації записує в рядок сесії вашу IP-адресу і рядок браузера (user-agent) — наш власний код їх не читає і профілів з них не будує. Аналітики і рекламних трекерів у застосунку немає взагалі.