Bezpieczeństwo

Szyfrowanie end-to-end, z kluczami na twoich własnych urządzeniach

Happier utrzymuje jedną sesję kodowania w synchronizacji między komputerem, na którym działa, a każdym urządzeniem, z którego ją oglądasz, a pośrodku tego stoi serwer relay. Ta strona jest architekturą pod tym zdaniem: który klucz powstaje gdzie, co relay faktycznie trzyma, co wciąż może zobaczyć i co się zmienia na serwerze skonfigurowanym tak, żeby wyłączyć szyfrowanie.

Jak wiadomość jest szyfrowana między twoim telefonem a twoim komputerem

Wiadomość, którą wysyłasz z telefonu, narysowana w trzech punktach, przez które przechodzi. Wszystko, co agent odpowiada, pokonuje tę samą drogę w przeciwnym kierunku, zapieczętowane na twoim komputerze, zanim go opuści.

Twój telefonTutaj zapieczętowane
RelayPrzenoszone zapieczętowane
Twój komputerTutaj otwierane
Twój telefon
Tutaj zapieczętowane. Wiadomość jest szyfrowana na urządzeniu, na którym ją napisałeś, kluczem należącym do tej sesji i do niczego więcej — 32 losowe bajty wylosowane przy tworzeniu sesji, AES-256-GCM, świeży nonce na każdą wiadomość. Klucz sesji jest następnie pieczętowany własnym kluczem twojego konta w efemerycznej wymianie X25519, i to zapieczętowaną kopię dostaje relay.
Relay
Przenoszone zapieczętowane. Serwer zapisuje wiersz o kształcie { t: "encrypted", c: "…" } — base64, plus zapieczętowana koperta klucza, do której nie ma klucza tajnego. Może ten wiersz trasować, policzyć, przechować i oddać. Nie ma czym go otworzyć i żaden endpoint go o to nie prosi.
Twój komputer
Tutaj otwierane. CLI otwiera zapieczętowany klucz sesji kluczem konta, który dostało przy podłączaniu terminala, odszyfrowuje i przekazuje jawny tekst do Claude Code, Codex, OpenCode albo tego agenta, który akurat działa. Odpowiedź pokonuje tę samą drogę w drugą stronę, zapieczętowana, zanim wyruszy.

Co przechowuje serwer relay

Szyfrowanie to twierdzenie o treści, a twierdzenie o treści jest tylko połową odpowiedzi. Oto druga połowa, z tą samą szczegółowością: kolumny, które operator tego relaya może odczytać bez klucza.

Trzyma
Szyfrogram i zapieczętowana koperta klucza
Jeden wiersz na wiadomość, zawierający base64 i nic poza tym, plus opakowany klucz danych tej sesji. Opakowanie odbywa się na urządzeniu; żadna trasa serwera go nie produkuje.
Identyfikatory i kształt
Identyfikatory konta, urządzenia i sesji, losowy tag na sesję, numery sekwencji, znaczniki czasu i rozmiary. To ta część, której szyfrowanie nie obejmuje w żadnym systemie, który się synchronizuje, i warto powiedzieć to wprost: relay wie, ile wysłałeś i kiedy.
Z której strony przyszła każda wiadomość
Każda wiadomość niesie rolę — użytkownik, agent, zdarzenie albo nieznana — podaną przez klienta obok szyfrogramu. To kolumna, dzięki której transkrypcję można stronicować i liczyć bez otwierania. W zaszyfrowanym wierszu serwer nie może jej wyprowadzić; może tylko przechować to, co zgłosił klient.
Celowo mała projekcja aktywności
Czy sesja jest nieprzeczytana, ile próśb o uprawnienia czeka, ile pytań zadał agent, czy myśli, jak skończyła się ostatnia tura. Każda z tych rzeczy to stan wyprowadzony — licznik, flaga albo znacznik czasu, który klient zapisuje w miarę ruchu sesji — nigdy słowo z tego, co zostało powiedziane. Istnieje po to, żeby telefon zamknięty od godziny pokazał poprawną plakietkę w chwili otwarcia, a liczenie jest maksimum tego, co serwer dostaje do tego zadania.
Nie trzyma
Co napisałeś i co odpowiedział agent
Transkrypcja jest szyfrogramem. Nie ma drugiej kopii, nie ma indeksu po stronie serwera i nie ma kroku podsumowania, który by go potrzebował.
Gdzie działa sesja
Ścieżka projektu, twoja nazwa hosta, twój katalog domowy i wersja CLI to metadane sesji, a metadane są szyfrowane tym samym kluczem sesji, zanim sesja powstanie. To pola wewnątrz zapieczętowanego bloba, a nie kolumny, po których serwer może sortować.
Twoje poświadczenia u dostawcy
Połączone konto — poświadczenie Claude albo ChatGPT, na którym działa sesja — jest pieczętowane na urządzeniu, zanim zostanie wysłane, kluczem wyprowadzonym do tego jednego celu z sekretu twojego konta. Relay przechowuje kopertę i oddaje ją twoim własnym urządzeniom.
Twoje repozytorium
Twoje repozytorium nigdy nie jest synchronizowane ani kopiowane. Agent czyta i zapisuje pliki na komputerze, na którym działa, i ten komputer pozostaje jedyną pełną kopią. Kiedy poprosisz o plik, folder albo diff, podróżują tą samą zapieczętowaną drogą co wszystko inne — bo o to poprosiłeś, a nie dlatego, że Happier trzyma kopię.

Twoje klucze szyfrujące powstają na twoim własnym urządzeniu

U korzenia twojego konta jest jeden sekret i powstaje on na urządzeniu — nie jest wydawany przez serwer. Wszystko inne wyprowadza się z niego drzewem kluczy: korzeń HMAC-SHA-512, a potem jeden krok HMAC na każdy etykietowany element ścieżki. Para kluczy otwierająca zapieczętowane klucze sesji wychodzi z tego drzewa pod etykietą "content", i tak samo osobny klucz dla każdego innego rodzaju przechowywanego bloba, więc żaden klucz nie wykonuje dwóch zadań.

Dlatego zupełnie nowa przeglądarka może zalogować się na twoje konto i wciąż nie pokazać ci niczego z zeszłego tygodnia. Zalogowanie dowodzi relayowi, kim jesteś. Odczytanie starej sesji wymaga klucza, a klucza nie ma na relayu, więc nie ma go skąd wysłać. Krokiem, który go przenosi, jest odtworzenie urządzenia — z urządzenia, które już go ma, albo z klucza tajnego, który zachowałeś.

Oznacza to też, że przypadek utraty jest realny i wart jednokrotnego powiedzenia: jeśli znikną wszystkie zalogowane urządzenia, a razem z nimi klucz tajny, zaszyfrowanych sesji nie odzyskamy ani my, ani nikt inny. Relay, który mógłby je oddać, byłby relayem, który mógłby je odczytać.

Podłączanie nowego urządzenia i jak trafiają na nie twoje klucze

Dodanie urządzenia to moment, w którym przenosi się materiał klucza, więc to moment wart zrozumienia. Zeskanowanie kodu QR podnosi żądanie i tyle: zatwierdzenie odbywa się na urządzeniu, które jest już zalogowane, a kiedy oba ekrany pokażą krótki kod potwierdzający, masz je porównać przed zatwierdzeniem.

Zatwierdzenie w rzeczywistości pieczętuje klucz treści kluczem publicznym urządzenia, które o niego poprosiło, w kopercie niosącej efemeryczny klucz nadawcy i świeży nonce. Ta koperta podróżuje przez relay tak jak wszystko inne. Podłączenie terminala dodaje jeszcze jedno powiązanie: ładunek jest uwierzytelniany względem sekretu parowania, który podróżował w kodzie QR, a nie przez serwer, więc relay, który podmieniłby ładunek, nie wyprodukowałby pasującego tagu.

Polityka przechowywania: szyfrowanie end-to-end jest domyślne

Wszystko powyżej opisuje ustawienie domyślne, a to ustawienie nie jest sugestią, z której klient może serwer wybić. Świeży relay jest ustawiony na wymóg przechowywania szyfrowanego end-to-end: zapis jawnym tekstem jest odrzucany błędem polityki, a nie po cichu przyjmowany. Klienci odczytują politykę z własnego endpointu features serwera, zanim utworzą sesję, więc tryb, w którym jest sesja, został uzgodniony przed jej pierwszą wiadomością.

Operator serwera ma do dyspozycji dwa inne ustawienia. Jedno pozwala decydować kontu, więc sesje szyfrowane i jawne współistnieją na tym samym relayu — wymaga to i polityki opcjonalnej, i zezwolenia na rezygnację, a zezwolenie jest wyłączone, dopóki operator go nie włączy. Drugie wymaga jawnego tekstu, dla organizacji, które zarządzają szyfrowaniem na poziomie infrastruktury i potrzebują serwera zdolnego odczytać i przetworzyć treść sesji. To ostatnie jest realnym kompromisem i warto powiedzieć to bez łagodzenia: w sesji jawnotekstowej serwer może odczytać transkrypcję. Na tym polega to ustawienie.

Tryb jest ustalany per sesja w chwili jej utworzenia, więc żadna sesja nie jest po połowie jednym i drugim, a zmiana trybu konta zmienia to, co dzieje się z nowymi sesjami, zamiast sięgać wstecz do starych. Nic nie jest odszyfrowywane wstecznie i nic nie jest wstecznie szyfrowane.

Zmienne, które ustawiają wszystkie trzy, opcje przechowywania pod nimi i kontrolki tożsamości wokół nich to operatorska połowa tej sprawy i mieszkają na stronie o własnym hostingu dla zespołów.

Powiadomienia push wysyła twój własny komputer

Powiadomienie push jest tą jedną rzeczą, która wychodzi poza ten model, bo musi dotrzeć do telefonu, na którym nic nie jest otwarte. Odpowiedź Happier jest taka, że wysyła je twój własny komputer. Serwer przechowuje twoje tokeny push; CLI na twoim własnym komputerze odczytuje je z powrotem i samo wysyła powiadomienie, co trzyma relay poza ścieżką, w której inaczej trzeba by mu podać treść.

To, co niesie ładunek, jest celowo skąpe: typ narzędzia albo żądania i krótka wskazówka tam, gdzie pomaga — plik taki jak src/file.ts, nazwa polecenia, liczba w rodzaju „3 pytania”. Surowe wejście narzędzia się w nim nie znajduje. Tyle, żeby zdecydować, czy sięgnąć po telefon, na ekranie, który przeczyta każdy stojący za tobą.

Relay hostowany u siebie: metadane też zostają na twoim sprzęcie

Wszystko to obowiązuje także na relayu, którego nie prowadzisz. Powodem, żeby prowadzić własny, jest wiersz powyżej o identyfikatorach i kształcie: szyfrowanie nie ukrywa, kto z kim rozmawia ani jak często, a na własnym relayu ten rejestr też jest twój. Jedno polecenie stawia relay na sprzęcie, który należy do ciebie, i ścieżka staje się: twoje urządzenie, twój relay, twój komputer, bez niczego, czego sam nie wdrożyłeś.

Przeczytaj kod szyfrowania samodzielnie

Na tej stronie nie ma certyfikacji, bo nie ma o czym donosić, a strona o bezpieczeństwie machająca zgodnością, której nie ma, jest gorsza niż taka, która o niej nie wspomina. Jest tu za to kod, z którego napisano każde powyższe zdanie, na licencji MIT i czytelny przed uruchomieniem: prymitywy w packages/protocol/src/crypto, szyfrowanie sesji w apps/cli/src/api/encryption.ts, polityka przechowywania egzekwowana przez serwer w jego endpoincie features oraz schemat pokazujący dokładnie, które kolumny są jawnym tekstem.

To także uczciwa odpowiedź na pytanie, jak traktować tę stronę: jako mapę tego, gdzie szukać, a nie jako obietnicę przyjmowaną na wiarę. Przeczytaj te cztery pliki albo uruchom relay sam i przeczytaj, co ogłasza swoim klientom.

Referencja modelu szyfrowania pokrywa ten sam obszar jako procedurę — czego wymaga od ciebie odtworzenie, co każdy tryb przechowywania oznacza dla konta, po który przepływ sięgnąć, gdy urządzenie nie może jeszcze odczytać sesji.