デバイスから当社へ送信される情報

このページは、Console とペアリングしたデバイスから、loopkeep を提供する 合同会社kumaaa(以下「当社」)が運用する Console と gateway へ送信される情報を説明します。 ペアリングしていないデバイスでは、ここに挙げる同期やリモート機能は動きません。cron、 file-watch、git、manual のトリガー、run、受信箱などのローカル機能は引き続きマシンだけで動きます。

ここでいう送信には、次の 2 つは含みません。

  • GitHub・Slack・webhook のイベント本文は、gateway からデバイスへ向かう逆方向のリレー通信です。 下のリレーと一時的な配送記録で区別して説明します。
  • workflow が safe output などを使って GitHub や Slack へ意図的に投稿・返信・通知する内容は、 選んだ第三者サービスへの出力です。当社の Console へ同期するデータではありません。

ペアリングと接続

ペアリングのブラウザフローでは、デバイスから次を送ります。

  • デバイス名とプラットフォーム(desktop)
  • デバイスが生成した Ed25519 公開鍵
  • 127.0.0.1 の一時コールバック URL と、応答を照合する 1 回限りの state

承認後、Console はデバイス ID、名前、プラットフォーム、公開鍵、デバイストークンのハッシュ、作成日時、 最終接続日時、最後に受け付けた active run スナップショット(空のものを含み、runs_updated_at として記録) の日時、無効化日時を記録します。一時コールバック URL と state はこのデバイス行には保存しません。 平文のトークンはデバイスへ 1 度だけ返し、以後の HTTPS・WebSocket 認証でデバイスが提示します。当社は 平文のトークンをデータベースに保存しません。署名用の秘密鍵はデバイスだけに残り、ペアリングでも その後の接続でも送信しません。

gateway への WebSocket 接続では、デバイスはプロトコルバージョン、デバイストークンと、対応機能を示す wake_signalsentitlement_pushremote_manualremote_run_controlremote_workflow_controlremote_automation_stop の各フラグを送ります。認証済みの API リクエストでも bearer トークンを送り、コントロールプレーンは最終接続日時を最短 1 分間隔で更新します。

その他の認証済みデバイスリクエスト

ペアリング済みデバイスは、編集画面やコネクタ操作に必要な情報を取得・管理するため、次の API リクエストも 送ります。いずれも上記の bearer トークンで認証します。

  • 名簿参照は kind と対象範囲を送ります。slack-users / slack-channelsteam_idgithub-users / github-labels / github-workflowsowner/name 形式の repogithub-reposinstallation_id を使います。結果はリクエストごとに Slack または GitHub から 取得し、Console には保存しません
  • パーソナル webhook の作成と削除は name を送ります。Console は名前、トークンのハッシュ、作成日時を 保存します。平文トークンを含む URL は作成または同じ名前での再発行時に 1 度だけデバイスへ返し、 データベースには保存しません。削除するとその行を削除します
  • Slack bot トークンの取得は team_id を送り、接続済み workspace の bot トークンを認証済みデバイスへ 返します。このトークンの目的とライフサイクルは プライバシーポリシーで説明しています
  • コネクタ一覧、アカウントプロフィール、パーソナル webhook 一覧の取得は、bearer 認証以外のリクエスト body や対象範囲のクエリパラメーターを送りません

workflow カタログ

daemon は Console の一覧と操作に使う完全な workflow カタログを、デバイス単位で送ります。 内容が変わると、以前のカタログを新しい全体で置き換えます。各カタログに含まれるのは次です。

  • workspace の ID と表示名
  • workflow 名
  • 宣言しているトリガー種別の粗い一覧
  • manual トリガーがあり、Console から開始できるかを示す runnable
  • 自動トリガーが無効かどうかを示す disabled。状態をまだ報告できない旧デバイスでは省略されます

このカタログには workflow の本文・ファイルパス・トリガーのフィルタ値を含めません。ただし、 外部イベントをルーティングするための詳しい宣言は、次の別データとして送ります。

トリガーのルーティング宣言

GitHub・Slack・webhook のイベントをどのデバイスのどの workflow へ届けるか判定するため、daemon は 外部トリガーの完全なルーティング宣言をデバイス単位で送ります。含まれるフィールドは次です。

  • workspace ID と workflow 名
  • app(githubslackwebhook)とイベント名
  • assigneelabelsactionsmentionsfromfrom_notreviewerconclusionsworkflowsbranchesemojion など、宣言したフィルタ名と値
  • GitHub の owner/name 形式のリポジトリ。省略した宣言は、その workspace の git origin から 解決したリポジトリを送ります
  • Slack のチャンネル ID と、webhook の hook 名

リポジトリやチャンネルの座標とフィルタ値は送られますが、リポジトリの内容、ローカルのファイルパス、 workflow 本文、プロンプト、policy、secret は送りません。

active run のスナップショット

リモート監督が有効なとき、daemon はデバイス上の非終端 run だけを集めた最新の完全な スナップショットを送ります。以前のスナップショットは、受け付けた新しい全体で置き換えます。 含まれるフィールドは次です。

  • workspace の ID と表示名
  • run ID、workflow 名、state、開始時刻
  • attendedtaken_overawaiting_hostawaiting_confirmfinishable の各フラグ
  • 起点の source、GitHub リポジトリの owner/name、および resource locator。locator は GitHub の issue 番号、pull request 番号、issue 番号と comment ID、または Slack のチャンネル ID・timestamp・ thread timestamp です

daemon が remote_supervision_enabled: false を認識している間は、スナップショットを組み立てず、 送信待ちのスナップショットも破棄します。remote_supervision_enabled が true から false に変わると、 コントロールプレーンは entitlement の変更と同じトランザクションで、アカウントに保存されたすべての active run 行をただちに削除します。次のデバイスアップロードを待つことはありません。機能が無効な間に デバイスがアップロードを試みると、コントロールプレーンはリクエストを解析・検証してから、現在の正となる entitlement を確認します。有効な形のスナップショットには HTTP 403 を返し、保存しません。一方、 entitlement の変更が届く前のリクエストや、すでに送信中のリクエスト body がネットワークを通ることまでは 防げないため、「無効なら常に 0 byte」とはみなしません。

スナップショットに、完了・失敗・中止した run の履歴、titlebodyauthorsession、worktree、 エンジン、プロンプト、イベントログ、受信箱、transcript は含めません。

Console からの run リクエストと制御

Console で人が開始・操作したリクエストは、まずコントロールプレーンに記録されます。run リクエストの 作成には remote_manual_enabled、制御の作成には remote_supervision_enabled が必要です。gateway の 通知はリクエストの idtenant_id だけを運び、workspace、workflow、action は運びません。 デバイスは id を使って内容を claim し、適用結果を送り返します。

  • run リクエストの記録はアカウント・デバイス、workspace、workflow、status、任意の run_id と 結果 message、作成・期限・決着日時を持ちます。デバイスの結果は idstatus (accepted / rejected)、作成した run の任意の run_id、短い message を運びます。
  • 制御の記録はアカウント・デバイス、actionstatus、任意の結果 message、作成・期限・決着日時を 持ちます。action は attended run の finish(workspace・run)、workflow の有効・無効を変える set_workflow_disabled(workspace・workflow・disabled)、自動化を停止する pause_automation です。 プロトコルには resume_automation もありますが、現在の Console は送らず、再開はローカルで行います。 デバイスの結果は制御の idstatus (accepted / rejected)、短い message を運びます。

run リクエストは作成から 2 分以内に claim する必要があります。いったん claim したリクエストの結果は、 2 分を過ぎても決着できます。制御は claim と結果の決着をどちらも作成から 2 分以内に行う必要が あります。結果メッセージはコントロールプレーンで 500 文字までに切り詰めます。run リクエストの記録は 作成から 30 日を過ぎると、新しい run リクエストの作成時と、Console の一部の workflow 一覧読み出し時に 削除対象として処理します。制御の記録は作成から 30 日を過ぎると、新しい制御の作成時だけ削除対象として 処理します。どちらのクリーンアップも失敗しても本来の処理を止めない best-effort の処理です。対応する 操作が起きない場合やクリーンアップに失敗した場合は 30 日を超えて残るため、30 日は保持の上限ではありません。

リレーと一時的な配送記録

購読した GitHub・Slack・webhook のイベントは gateway からデバイスへ向かいます。これは デバイスから当社への同期ではありませんが、配送を完了するために次の一時記録を使います。

  • 未 ack キューは wake signal と対象デバイス ID、期限を持ちます。signal には id、アカウントを示す tenant_idsourceinstallation_id / team_id / hook_ideventoccurred_at、 リポジトリの repo、resource locator の resource、一致した workspace・workflow の matchedreplayed、イベント本文の body が含まれます。任意フィールドはイベントの種類によって省略されます
  • bodytitletextauthorurlchannel_namesenderpermalinktruncated です。取得できない任意フィールドは省略されます。text は先頭 64 KiB までで、切り詰めると truncatedtrue になります
  • デバイスは処理を確定すると wake signal の id だけを ack として返します。gateway は正しい対象 デバイスの ack を受けると、本文を含むキューエントリと ID の索引を削除します
  • デバイスがオンラインかオフラインかに関係なく、キューはアカウントあたり未 ack のエントリを最大 1,000 件保持します。各エントリは作成から 24 時間で配送資格を失い、それ以後は再配送しません。 期限切れエントリの物理削除は通常 1 時間ごとの定期クリーンアップで行うため、保存領域から消える時刻は 24 時間より後になることがあります。上限を超えると最古のエントリを削除し、そのエントリは以後配送しません
  • 重複判定には wake signal ID と作成から 24 時間の期限だけを保持します。期限後は重複とみなさず、 ID の物理削除は次の参照または定期クリーンアップで行います
  • wake signal のクォータと配送停止理由は UTC 日ごとの集計件数です。本文は含まず、当日を含む 直近 3 日分(当日とその前の 2 日)を対象に保持します。それより古い件数は、4 日目の UTC 00:00 以降に動くクリーンアップで削除対象になります
  • レート制限のため、アカウント全体の ratebucket と、一致した workspace の ID を含む wsrate:<workspace> ごとに、トークン残数の tokens と補充計算の基準時刻 ts を保存します。 これらにイベント本文は含みません。現行実装には、このバケットを時間だけで自動削除する経路はありません

配送停止理由は no_specno_matchnot_visiblevisibility_unknowndm_not_addressedbody_too_largerate_limitedno_connectionsduplicatequota_exceededworkspace_rate_limitedqueue_overflowqueue_expiredqueue_target_missingdevice_revoked です。Consoleとはでは、イベントが届く流れと Console に表示する この集計を説明しています。

gateway のキャッシュと接続のライフサイクル

gateway はルーティング、認証、現在の接続状況のために、次のコピーも持ちます。これらはデバイスからの 追加アップロードではありませんが、コントロールプレーンの変更が gateway に反映される時期を左右します。

コピー内容ライフサイクル
トークンルーティングroute:token:<token-hash> はデバイストークンの SHA-256 ハッシュを tenant_id へ対応付けます。存在しない、または無効化済みのトークンは none を保持します有効な対応は 10 分、none は 60 秒です
トリガールーティングrouting:installation:*routing:team:*routing:hook:* はアカウントの identity と entitlement、デバイスごとのトリガー宣言、任意のパーソナル webhook の hook 名を持ち、routinglast:* は最後に取得できたコピーを持ちます通常の結果は none を含め 10 分です。最後に取得できたコピーは 1 時間で、コントロールプレーンの取得に失敗したときだけ使います
デバイス認証device:<token-hash>device_idtenant_idpublic_keyrevokedexpiresAt を持ちます10 分間有効です。期限は論理的なもので、期限切れのコピーは次の remote_hello で更新または削除するまで保存領域に残ることがありますが、そのコピーだけで新しい接続を認証しません
entitlemententitlementsentitlements_exp は tenant gateway が使うアカウントの entitlement を持ちますentitlements_exp がある値は 10 分間期限内です。wake で転送された entitlement は、期限内のキャッシュがないときだけ置き換えます。取得または entitlement_update push に成功したときも置き換えます。コントロールプレーンの障害中に最後に取得した値を使うのは、デバイス認証キャッシュがまだ有効な場合だけです。entitlements_exp がない以前の形式の値は、期限なしで期限内として扱います。期限切れは論理的な判定で値を削除しないため、置き換えるまで物理的に残ることがあります
ソケット attachment接続中の WebSocket は autheddeviceIdremote_hello で宣言した対応機能の各フラグを持ちます休止をまたいで同じ論理 WebSocket 接続が続く間保持し、接続が閉じると終わります

device_revoked push が届くと、gateway は該当するソケットを必ず閉じ、該当する未 ack キューを破棄します。 device:<token-hash> の各エントリを調べ、device_id が一致する場合だけ、そのデバイス認証コピーと対応する route:token:<token-hash> のキーを削除します。この push はトリガールーティングのコピーを削除しません。 別の routing_purge が、通常と最後に取得できたトリガールーティングのコピーを両方削除します。それぞれの push は到達を保証しません。遅延または欠落した場合は、該当する上記キャッシュの期限か論理接続の終了まで コピーが使われることがあります。

送信しないもの

次の内容は、この同期やリモート監督のために当社へ送りません。

  • リポジトリと作業ファイルの内容、.env、secret の値、デバイスの秘密鍵
  • workflow 本文とファイルパス、policy、プロンプト
  • イベントログ、受信箱とアテンション、完了した run の履歴と transcript
  • active run の titlebodyauthorsession・worktree・エンジン

一方、上で列挙したデバイス名、workspace の表示名、workflow 名、リポジトリ・チャンネルの座標、 トリガーのフィルタ、非終端 run のメタデータは送信対象です。「コードや本文を送らない」と 「メタデータを一切送らない」は同じ意味ではありません。また、ここでの除外はデバイスからのカタログ・ ルーティング・run 同期についてのものです。逆方向のリレーでは、前節のとおりイベント本文を一時保持します。

置き換え、無効化、削除

  • workflow カタログ、ルーティング宣言、受け付けた active run スナップショットは、デバイスから届く 最新の完全な内容で置き換えます。これらのコントロールプレーン行には、通常の時間ベースの自動削除期限は ありません
  • remote_supervision_enabled が true から false に変わると、entitlement の更新と同じトランザクションで、 アカウントに保存されたすべての active run 行をただちに削除します。次のアップロードを待つことはなく、 機能が無効な間にあとから送信された有効な形のスナップショットには HTTP 403 を返して保存しません
  • Console でデバイスを 無効化 すると、コントロールプレーンのトランザクションでそのデバイスを直ちに 無効化し、workflow カタログ、ルーティング宣言、active run スナップショットを削除します。その後、 コントロールプレーンはそのトークンを受け付けません
  • lk logout の無効化リクエストが成功すると、Console の 無効化 と同じコントロールプレーンの トランザクションでトークンを無効化し、workflow カタログ、ルーティング宣言、active run スナップショットを削除します
  • 非同期の Clerk user.deleted webhook を処理すると、そのアカウントのデバイス、カタログ、 ルーティング宣言、run スナップショット、run リクエスト、制御を含むコントロールプレーンの関連行を 連鎖削除します

これらのコントロールプレーン行の変更と、gateway への反映は別です。Console の 無効化lk logout、アカウント削除はいずれも、到達を保証しない device_revoked push を試みます。Console の 無効化 とアカウント削除は routing_purge も試みますが、lk logout は試みません。それぞれの push が 削除する範囲は上記のとおり別です。push が遅延または欠落してもコントロールプレーンの削除は取り消されませんが、 gateway の該当するコピーを、論理的な期限が切れるか接続が終了するまで使い続けることがあります。物理的な保存は 上表に従います。 期限切れのデバイス認証コピーは後の remote_hello まで、entitlement 値は置き換えまで残ることがあり、 entitlements_exp のない以前の entitlement には期限がない場合があります。未 ack キューは 24 時間の 期限後は再配送せず、その後の定期クリーンアップで物理削除します。コントロールプレーンの連鎖削除は gateway の保存領域を直接削除しないため、重複判定 ID と UTC 日次件数は上記の期限・クリーンアップに従い、レート制限用 バケットには現行実装上の時間ベースの自動削除経路がありません

個人データの取り扱い全体、連携、Cookie、委託先、お問い合わせについては、 プライバシーポリシーを参照してください。