エンドツーエンド暗号化、鍵はあなた自身のデバイスの上に
Happier は 1 つのコーディングセッションを、それが動いているコンピュータと、あなたがそれを見るすべてのデバイスの間で同期させ、その真ん中にはリレーサーバーがいます。このページは、その一文の下にあるアーキテクチャです。どの鍵がどこで作られるのか、リレーが実際に保持しているものは何か、それでもリレーに見えるものは何か、そして暗号化をオフにするよう設定されたサーバーでは何が変わるのか。
携帯電話とコンピュータの間で、メッセージがどう暗号化されるか
携帯電話から送ったメッセージを、それが通過する 3 つの地点で描いたものです。エージェントが返すものはすべて同じ経路を逆向きにたどり、あなたのコンピュータを離れる前に封をされます。
- あなたの携帯電話
- ここで封をする. メッセージは、それを打ち込んだデバイスの上で、そのセッションだけに属する鍵で暗号化されます — セッションの作成時に引かれる 32 バイトの乱数、AES-256-GCM、メッセージごとに新しいノンスです。次にそのセッション鍵は、一時的な X25519 の鍵交換であなたのアカウント自身の鍵に対して封をされ、リレーに渡されるのは封をされた方のコピーです。
- リレー
- 封をしたまま運ぶ. サーバーが書き込むのは { t: "encrypted", c: "…" } という形の行です — base64 と、秘密鍵を持たない封をされた鍵のエンベロープです。サーバーはその行をルーティングし、数え、保持し、返すことができます。開くための手段は何も持っておらず、それを求めるエンドポイントもありません。
- あなたのコンピュータ
- ここで開く. CLI は、ターミナルを接続したときに渡されたアカウントの鍵で、封をされたセッション鍵を開き、復号し、平文を Claude Code、Codex、OpenCode、あるいは動いているエージェントに渡します。返信は同じ道を逆にたどり、出る前に封をされます。
リレーサーバーが保存するもの
暗号化は内容についての主張であり、内容についての主張は答えの半分にすぎません。もう半分を、同じ詳しさで示します。このリレーを運用するサーバーが鍵なしで読める列です。
- 暗号文と、封をされた鍵のエンベロープ
- メッセージごとに 1 行、base64 だけを保持し、加えてそのセッションのラップされたデータ鍵があります。ラップはデバイスの上で行われ、それを生成するサーバーのルートはありません。
- 識別子と形
- アカウント、デバイス、セッションの ID、セッションごとのランダムなタグ、シーケンス番号、タイムスタンプ、サイズです。これは、同期するシステムなら暗号化が覆わない部分で、はっきり言っておく価値があります。リレーは、あなたがどれだけ、いつ送ったかを知っています。
- 各メッセージがどちら側から来たか
- すべてのメッセージは、暗号文と一緒にクライアントが渡す役割 — user、agent、event、unknown — を持ちます。これは、トランスクリプトを開かずにページングして数えられるようにするための列です。暗号化された行では、サーバーはそれを導き出せません。クライアントが提出したものを保存できるだけです。
- 意図的に小さくした活動の射影
- セッションが未読かどうか、いくつの権限リクエストが待っているか、エージェントがいくつ質問したか、思考中かどうか、直前のターンがどう終わったか。どれも、セッションが進むにつれてクライアントが書く、カウンタ、フラグ、タイムスタンプといった派生的な状態であって、話された内容は一言も含みません。これは、1 時間閉じていた携帯電話を開いた瞬間に正しいバッジが出るように存在していて、そのためにサーバーに任せているのは、数えることまでです。
- あなたが打ったものと、エージェントが返したもの
- トランスクリプトは暗号文そのものです。2 つ目のコピーも、それに対するサーバー側のインデックスも、それを必要とする要約の処理もありません。
- セッションが動いている場所
- プロジェクトのパス、ホスト名、ホームディレクトリ、CLI のバージョンはセッションのメタデータで、メタデータはセッションが作成される前に同じセッション鍵で暗号化されます。これらは封をされたブロブの中のフィールドであって、サーバーが並べ替えられる列ではありません。
- プロバイダの資格情報
- 接続されたアカウント — セッションが使う Claude や ChatGPT の資格情報 — は、アップロードされる前にデバイスの上で、その目的のためだけにあなたのアカウントの秘密から導出した鍵で封をされます。リレーが保存するのはエンベロープで、それをあなた自身のデバイスに返します。
- あなたのリポジトリ
- リポジトリが同期されたりミラーされたりすることはありません。エージェントは動いているコンピュータの上でファイルを読み書きし、そのコンピュータが唯一の完全なコピーであり続けます。ファイル、フォルダ、差分を求めたときは、他のすべてと同じ封をされた経路を通ります — あなたが求めたからであって、Happier がコピーを持っているからではありません。
暗号鍵は、あなた自身のデバイスの上で生成されます
あなたのアカウントの根には秘密が 1 つあり、それはサーバーから発行されるのではなく、デバイスの上で作られます。他のすべては鍵のツリーによってそこから導出されます。HMAC-SHA-512 の根があり、ラベルの付いたパスの要素ごとに HMAC のステップが 1 つずつ続きます。封をされたセッション鍵を開く鍵ペアは、そのツリーの「content」というラベルの下から出てきますし、保存される他の種類のブロブそれぞれにも別の鍵が出てきます。どの鍵も 2 つの仕事をしません。
だからこそ、真新しいブラウザがあなたのアカウントにサインインできても、先週の内容を何も表示できません。サインインは、あなたが誰かをリレーに対して証明します。古いセッションを読むには鍵が要り、その鍵は、送るためにリレーの上にはありません。それを移すのはデバイスの復元という手順で、すでに鍵を持っているデバイスから、あるいは保管しておいた秘密鍵からです。
これは同時に、失う場合が現実にあり、一度はっきり述べておく価値があることも意味します。サインイン済みのデバイスがすべてなくなり、秘密鍵も一緒になくなったなら、暗号化されたセッションは私たちにも誰にも復元できません。それを返せるリレーは、それを読めるリレーだということになります。
新しいデバイスをリンクするとき、鍵はどうやってそこへ届くか
デバイスの追加は鍵の材料が動く瞬間なので、理解しておく価値のある瞬間です。QR コードを読み取るとリクエストが上がり、それだけです。承認はすでにサインインしているデバイスの上で行われ、両方の画面に短い確認のコードが表示されたら、承認する前に見比べることになっています。
承認が実際にすることは、要求してきたデバイスの公開鍵に対してコンテンツの鍵を封じることで、エンベロープには一時的な送信者の鍵と新しいノンスが入ります。そのエンベロープは、他のすべてと同じようにリレーを通ります。ターミナルの接続では、その上にもう 1 つの束縛が加わります。ペイロードは、サーバーではなく QR コードで運ばれたペアリングの秘密に対して認証されるので、ペイロードを差し替えたリレーは一致するタグを作れません。
ストレージのポリシー: 既定はエンドツーエンド暗号化
以上のすべては既定について述べたもので、その既定は、クライアントがサーバーを説得して覆せる提案ではありません。新しいリレーは、エンドツーエンド暗号化されたストレージを必須とするよう設定されています。平文の書き込みは、黙って受け入れられるのではなく、ポリシーのエラーで拒否されます。クライアントはセッションを作成する前にサーバー自身の features エンドポイントからポリシーを読むので、セッションがどのモードにあるかは、最初のメッセージの前に合意されています。
サーバーの運用者には、ほかに 2 つの設定があります。1 つはアカウントに選ばせるもので、暗号化されたセッションと平文のセッションが同じリレーの上で共存します — これには任意のポリシーとオプトアウトの許可の両方が必要で、その許可は運用者が有効にしない限りオフです。もう 1 つは平文を必須にするもので、インフラの層で暗号化を管理し、サーバーがセッションの内容を読んで処理できる必要がある組織向けです。最後のものは実際のトレードオフであり、和らげずに言う価値があります。平文のセッションでは、サーバーはトランスクリプトを読めます。それがその設定の目的です。
モードは作成時にセッションごとに固定されるので、1 つのセッションが半分ずつになることはありませんし、アカウントのモードを変えても、古いものにさかのぼるのではなく、新しいセッションの扱いが変わります。さかのぼって復号されるものも、さかのぼって暗号化されるものもありません。
その 3 つすべてを設定する変数、その下にある保存時の選択肢、そしてそれらを取り巻く ID の制御は、運用者側の半分であり、チーム向けのセルフホストのページにあります。
プッシュ通知は、あなた自身のコンピュータが送ります
プッシュ通知は、このモデルから唯一はみ出すものです。何も開いていない携帯電話に届かなければならないからです。Happier の答えは、あなた自身のコンピュータがそれを送る、というものです。サーバーはあなたのプッシュのトークンを保存し、あなた自身のコンピュータの上の CLI がそれを読み戻して、自分で通知を送ります。そうすることで、本来なら内容を伝えなければならない経路からリレーを外せます。
ペイロードが運ぶ内容は意図的に薄くしてあります。ツールまたはリクエストの種類と、役に立つ場合の短いヒント — src/file.ts のようなファイル、コマンドの名前、「3 questions」のような件数 — です。ツールの生の入力は入れません。携帯電話に手を伸ばすかどうかを判断するのに足りるだけで、後ろに立っている人が読める画面に出るものです。
セルフホストのリレー: メタデータもあなたのハードウェアの上に留まります
以上のすべては、あなたが運用していないリレーの上でも成り立ちます。自分で運用する理由は、識別子と形についての上の行にあります。暗号化は、誰が誰と、どれくらいの頻度で話しているかを隠しません。自分のリレーなら、その台帳もあなたのものです。コマンド 1 つでリレーはあなたが所有するハードウェアの上に置かれ、経路はあなたのデバイス、あなたのリレー、あなたのコンピュータになり、その中にあなたがデプロイしていないものはありません。
暗号化のコードを自分で読む
このページに認証の記載がないのは、報告できるものがないからで、持っていないコンプライアンスをほのめかすセキュリティのページは、それに触れないページより悪いからです。代わりにここにあるのは、上のすべての文がそこから書かれたコードです。MIT ライセンスで、実行する前に読めます。packages/protocol/src/crypto のプリミティブ、apps/cli/src/api/encryption.ts のセッションの暗号化、サーバーが features エンドポイントで適用するストレージのポリシー、そしてどの列が平文かを正確に示すスキーマです。
それは、このページをどう扱うべきかについての正直な答えでもあります。信じて受け取るべき約束ではなく、どこを見ればよいかの地図として扱ってください。4 つのファイルを読むか、自分でリレーを動かして、それがクライアントに何を告知するかを読んでください。
暗号化モデルのリファレンスは、同じ範囲を手順として扱います。復元が何を求めるか、各ストレージのモードがアカウントにとって何を意味するか、デバイスがまだセッションを読めないときにどのフローを選ぶか、です。

