Тепер трохи технічно.
Усе, що каже головна сторінка, виписане як те, з чого це зроблено. Справжня база даних, як насправді виникає контакт, і хто ще торкається дзвінка.
Ця сторінка не потрібна, щоб користуватися Rilo, і ніщо тут не суперечить простішій версії. Це той самий продукт, описаний точно.
Уся база даних
Усе, що наш сервер знає про твою сім’ю.
Не стислий виклад. Це сімнадцять таблиць, які має сервер, з тими стовпцями, які в них справді є. Чотири про твою сім’ю. Хто вони, хто може діяти за дитину, з яких телефонів вони говорять і куди їм дзвонити. Чотири тримають щось для телефона, який був вимкнений, і всі чотири стирають себе самі. Три про те, хто може діяти за дитину і який телефон перестав бути довіреним. Ще дві зберігають підписаний слід завершення. Розірваний контакт або людина, яка пішла. Вони лишаються, щоб телефон, який був офлайн, міг перевірити їх сам, а не вірити нам на слово. В одній лежать витрачені одноразові числа, які прибирають, щойно вони згасають. Одна про підписку, і в ній немає нічого, що когось називає. Ще в одній лежить скарга, яку надіслав дорослий, і це єдина таблиця тут, яка існує, щоб щось сталося. Остання зовсім не про твою сім’ю.
- idхеш відкритого ключа, не ім’я
- public_keyключ пристрою, який і є обліковим записом
- typeдорослий або дитина
- type_certпідпис, який це доводить. Дитячий обліковий запис підписує батько або мати, тому тут немає прапорця, який можна перемкнути
- created_at
- last_activeостанній раз, коли якийсь із твоїх телефонів привітався
- dormant_warned_atпорожньо
- consent_sealedтвоя пошта з реєстрації, запечатана ключем, який лежить на папері у засновника. Жоден сервер не може її прочитати
- uncovered_sinceпорожньо, якщо твій план перестав охоплювати цю дитину — тоді день, коли ми це помітили, щоб місяць до того, як щось зупиниться, рахувався з цієї дати
- keyщо саме запам’ятовується
- valueі що воно каже
- account_id
- guardian_keyключ, якому дозволено діяти за цю дитину
- added_at
- removed_at
- account_id
- device_keyвласний ключ одного телефона. Людина може говорити більше ніж з одного
- agreement_keyключ, на який запечатують повідомлення, щоб відкрити його міг лише цей телефон
- certпідпис, який впустив цей телефон, збережений слово в слово, щоб твій телефон міг його перевірити, а не вірити нам
- kindтелефон або надрукований аркуш для відновлення
- added_at
- removed_at
- account_id
- device_keyкотрий із твоїх телефонів будить цей рядок
- platformapns або fcm
- tokenнепрозорий ідентифікатор від Apple або Google
- updated_at
- nonce
- expires_at
- edge_hashхеш пари, не двох людей
- denied_at
- expires_at
- edge_hashхеш пари, не двох людей
- grant_recordдозвіл, про який ідеться, і підписи, зібрані досі
- waiting_keyчийого підпису ще бракує
- requested_byтелефон, який попросив, щоб один телефон не міг залити сім’ю питаннями
- originвідскановано особисто або батько чи мати діють за свою дитину
- delivered_toякі телефони це вже мають
- declaredвласне ім’я тієї сторони, яка просить, запечатане так, що прочитати його може лише сім’я, яку вона відсканувала
- created_at
- expires_at
- id
- recipient_idдля маршрутизації цей потрібен відкритим
- recipient_deviceдля котрого з їхніх телефонів запечатано коробочку. Кожен телефон має свій ключ, тож кожен отримує свою коробочку
- sender_idщоб телефон знав, чий ключ її відкриває
- sender_deviceкотрий із їхніх телефонів її запечатав, щоб правильна копія знайшла правильний замок
- edge_hashпара, у вигляді хешу, щоб це не читалося як карта того, хто з ким говорить
- sealedшифротекст. Стовпця з текстом немає і ніколи не буде
- sent_at
- expires_at
- edge_hashпара, у вигляді хешу
- revoked_at
- recordпідписаний запис, щоб телефон, який був офлайн, перевірив розрив сам, а не вірив нам на слово
- id
- account_idчий список телефонів і дорослих змінюється
- kindприєднання або прибирання
- subject_keyтелефон або дорослий, про якого йдеться
- subject_kindкотре з цих двох
- agreement_keyдругий ключ, потрібний телефону, порожньо для паперу
- recordсам підпис, збережений слово в слово, щоб телефон міг його перевірити, а не вірити нам
- signed_byякий ключ це підписав
- by_authorityчи підписав це аркуш для відновлення, і саме через це воно чекає
- issued_atмить, яку заявляє той, хто підписав, ніколи наш годинник
- reasonпорожньо, якщо той, хто підписав, нічого не написав
- proposed_at
- effective_atколи це стає правдою, через дві ночі після того, як запропонували
- contested_at
- contested_byхто заперечив і яким підписом він заперечив
- contest_record
- resolved_at
- resolutionзастосовано або скасовано, коли все вирішилося
- change_idяка саме зміна чекає
- voter_keyякий дорослий
- decisionпропустити або зупинити
- recordйого підпис
- at
- account_idчий це був телефон
- device_keyключ, який украли
- revoked_at
- recordпідписаний доказ, щоб телефон міг перевірити його, не питаючи нас
- account_idобліковий запис, якого більше немає
- retired_at
- recordпідписаний доказ, зроблений власним ключем того облікового запису, перш ніж ключ знищили
- account_id
- storeapple, google або від нас
- store_refнепрозорий ідентифікатор від магазину. Це єдине, що дозволяє нам пізніше поставити йому питання
- store_ref_hashвідбиток ідентифікатора вище. Саме він не дає одному чеку покрити два облікові записи
- environment
- stateactive, grace, lapsed, lapsed_trial або disabled
- seatsскільком дітям це покриває. Число, ніколи їхні імена
- expires_at
- acts_at
- updated_at
- device_keyтелефон, якому ще не сказали
- change_idпро яку саме зміну йдеться
- whatзапропоновано, оспорено або вирішено
- account_idчий список телефонів змінився. Коли дорослому кажуть про його дитину, тут стоїть дитина
- subject_keyтелефон, який додали або прибрали
- effective_at
- created_at
- expires_at
- delivered_atколи нам удалося це сказати, або порожньо, бо не вдалося
- id
- about_keyпро кого скарга. Читабельно, щоб хтось міг за нею щось зробити
- reasonяка з шести речей сталася, так, як це обрав дорослий, що скаржиться
- csa
- sealedщо було написано, запечатане на телефоні, який це надіслав, ключем, що лежить на папері у засновника. Жоден сервер не може це прочитати
- sealed_digestвідбиток запечатаної частини, щоб те, що відкриють згодом, доказово було тим, що прийшло
- received_at
- edge_snapshotкому було дозволено когось досягати і який дорослий це дозволив, як воно стояло в ту мить. Це відтворити пізніше неможливо
- reporter_keyхто надіслав, або нічого взагалі, коли надіслали без імені
- source
- sealed_key
- receiptномер, який лишається у відправника. Це єдиний спосіб, яким ми можемо комусь відповісти про скаргу, якої не можемо відкрити
- acknowledged_at
- decided_at
- actioned_at
- escalated_at
- decided_by
- outcome
Стовпці, яких не існує
- пошта
- ім’я
- вік
- фото
- текст повідомлення
- вміст дзвінка
- історія дзвінків
- список контактів
- місце
- модель пристрою
Твою пошту перевіряють один раз під час реєстрації і в тому самому подиху запечатують ключем, який лежить на папері у засновника і ніколи не торкався сервера. Закон просить, щоб ми могли довести, що дорослий погодився. Прочитати її назад ми й самі не змогли б. Імена й фото ставлять на кожному телефоні і передають прямо іншому телефону. До нас вони не доходять, і саме тому ти можеш назвати дідуся “Дідою”, а ми ніколи про це не дізнаємось. Ми не змогли б нічого з цього комусь показати, навіть якби хотіли, і нас не можна до цього змусити.
Цей розділ згенеровано зі власної схеми сервера, з accounts.ts і roster-changes.ts, двох файлів, які створюють базу даних. Якщо вони колись розійдуться, праві файли, а ця сторінка помиляється.
Контакти
Як насправді виникає контакт.
Чийсь телефон робить одноразове запрошення. Інший телефон його читає, відсканувавши з екрана в тій самій кімнаті або відкривши з посилання, яке надіслав дорослий. Це читання починає знайомство і в ту саму мить записує відкритий ключ іншого телефона, тож обидва телефони відтоді точно знають, який ключ комусь належить. Саме ця частина робить неможливим вклинитися посередині пізнішого дзвінка, і для нас теж. Ніщо з цього не з’єднано, поки дорослий з іншого боку не скаже «так».
Це ще не контакт. Відповідальний дорослий мусить підписати контакт на власному телефоні, після біометричної перевірки, зробленої в ту саму мить. Він підписує все цілком. Хто, з ким і в якому напрямку. Саме цей підпис сервер перевіряє, перш ніж щось передати. Сервер не тримає жодного ключа, яким можна підписати, тож він не може створити контакт, і той, хто вкраде базу даних, теж не може.
Коли обидва телефони мають завершений контакт, рядок стирають, і контакт існує лише на двох пристроях. Розрив пізніше пише підписане відкликання, і це єдиний запис, який лишається безстроково. Він зберігається як хеш пари, тож він каже, що контакт скінчився, не кажучи, хто когось знав.
Хто ще причетний
Дзвінка торкаються три компанії. Жодна з них не може його почути.
Сервісу торкаються ще шість компаній, і всі вони перелічені в політиці приватності. Три з них потрібні, щоб дзвінок задзвонив. Ось що кожна з цих трьох бачить і чого не бачить.
-
Apple & Google
Пуш-повідомлення, щоб дзвінок задзвонив на телефоні, який спить. На обох платформах цього не обійти. Вони несуть непрозорий ідентифікатор і більше нічого. Ні імені, ні номера, ні вмісту.
-
Cloudflare
Приблизно один дзвінок із шести не може з’єднати два телефони напряму, у готельному Wi-Fi або в деяких мобільних мережах, і його відбивають через ретрансляцію. Ретрансляція передає зашифровані пакети, яких не може відкрити, але вона таки бачить, що два анонімні ідентифікатори були з’єднані, коли, як довго і з яких адрес. Це метадані, яких ми не зберігаємо, і які лежать у когось іншого.
-
Ми
Таблиця вище. Один невеликий сервер у Нідерландах, який знайомить два телефони і потім відходить убік.