kagi

kagi

秘密トークンを承認者のスマホのブラウザー内に持ち、API コールを検閲する。 リクエスト元(スクリプトや AI エージェント)は秘密を知らないまま、承認された API コールの結果だけを受け取る。

承認者の画面を開く

流れ

  1. 承認者はスマホでこのサイトをホーム画面に追加し、マイページ でサインインして通知を登録する。
  2. 承認 で秘密を保存する。秘密は localStorage に、パスキー(WebAuthn PRF)で暗号化して置かれ、サーバーには送られない。
  3. 同じ画面で端末を承認者として登録すると、リクエスト用の URL (/api/sub/:id/req)が発行される。
  4. リクエスト元が POST /api/sub/:id/req に、秘密を [NAME] で埋めたリクエストを送る。サーバーは承認者のスマホに push 通知し、transaction_id を返す。
  5. 承認者は内容(送信先ホスト・ヘッダー・ボディ)を見て、パスキーで承認する。 ブラウザーが秘密を埋めて API を呼び、結果を手元に保持する。
  6. リクエスト元の GET /api/sub/:id/res?transaction_id=… に、サーバーが WebSocket 越しにスマホから結果を取り寄せて返す(一度だけ)。 結果に含まれる秘密の値は [NAME] に置き換えられる。

リクエストの形

POST /api/sub/:id/req
{
  "secrets": ["GH_SECRET"],
  "url": "https://api.github.com/user",
  "method": "GET",
  "headers": { "authorization": "Bearer [GH_SECRET]" },
  "body": {}
}
→ 202 { "transaction_id": "…", "status": "pending", "notified": true }

GET /api/sub/:id/res?transaction_id=…&wait=25
→ 200 { "status": "delivered", "response": { "status", "headers", "body" } }
→ 202 { "status": "pending" }   まだ決まっていない(再度呼ぶ)
→ 403 / 502 / 410               拒否 / 呼び出し失敗 / 期限切れ・受け渡し済み

API はブラウザーから呼ばれるので、呼び先が CORS でこのオリジンを許可している必要がある。