> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Outposts パートナー統合

> PKCE コード交換を使用してパートナープラットフォームから アウトポスト を接続

<Note>
  暫定メモ — このフローはまだ開発初期段階にあるため、以下の詳細は
  変更される可能性があります。
</Note>

パートナープラットフォーム (コンピュートプロバイダーなど) は、顧客に代わって アウトポスト を接続できます。顧客側の Devin 管理者がブラウザで接続を承認すると、Devin は アウトポスト とサービスユーザーを作成し、パートナーにその アウトポスト に対してワーカーを実行するためのトークンを渡します。

このフローは、[PKCE](https://datatracker.ietf.org/doc/html/rfc7636) を使用した簡易的な OAuth 認可コード交換です。ブラウザで扱われるのは、有効期間が短く一度しか使えない **コード** のみで、サービスユーザーのトークンはサーバー間で交換されるため、ブラウザを経由することはありません。

<div id="prerequisites">
  ## 前提条件
</div>

* **コールバックの許可リスト。** 利用するすべての `callback_url` は、その統合用の Devin の許可リストに登録されている必要があります。これは Cognition 側で設定するため、事前に正確な URL をお知らせください。リストにない URL は拒否されます。
* **Outposts が有効であること。** 顧客のアカウントで Outposts が有効になっている必要があります。
* **管理者による承認。** 接続の承認には、`enterprise-settings` と サービスユーザー 管理の両方の権限を持つ Devin 管理者が必要です。パートナーが Devin トークンを必要とすることはありません。管理者が自身のブラウザのセッションで承認します。

<div id="flow-overview">
  ## フローの概要
</div>

```
パートナーバックエンド           管理者のブラウザ                 Devin
     │                                │                            │
     │ 1. code_verifier を生成し、     │                            │
     │    code_challenge を導出        │                            │
     │ 2. app.devin.ai/outposts/connect?…code_challenge へリダイレクト│
     │───────────────────────────────>                            │
     │                                │ 3. 管理者が「Connect」を確認│
     │                                │──────confirm connection──────>
     │                                │ 4. redirect callback_url?code=…  │
     │<───────────────────────────────                            │
     │ 5. POST /outposts/connection-token  (code + code_verifier) │
     │────────────────────────────────────────────────────────────>
     │ 6. { access_token, api_base_url, … }                       │
     │<────────────────────────────────────────────────────────────
     │ 7. access_token を使用してoutpost ワーカーを起動         │
```

<div id="1-generate-a-pkce-verifier-and-challenge">
  ### 1. PKCE の verifier と challenge を生成する
</div>

バックエンドで、接続の試行ごとに次を行います。

* 高エントロピーのランダムな **`code_verifier`** を生成します。文字数は 43～128 文字で、使用する文字は未予約文字 `[A-Za-z0-9-._~]` に限ります (例: パディングを除いた `base64url(random 32 bytes)`) 。
* verifier の SHA-256 をパディングなしの base64url で表したものとして、**`code_challenge`** を導出します (PKCE "S256") :

```python theme={null}
import base64, hashlib, secrets

code_verifier = secrets.token_urlsafe(32)  # 43文字以上、予約されていない文字のみ使用
code_challenge = (
    base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest())
    .rstrip(b"=")
    .decode()
)
```

`code_verifier` はサーバー側に保存してください (最終的に返ってくるコールバックと対応付けるために利用する state にひも付けます) 。verifier は絶対にブラウザに送信しないでください。バックエンドから渡すのは challenge のみです。

<div id="2-redirect-the-admin-to-the-connect-page">
  ### 2. 管理者を接続ページにリダイレクトする
</div>

challenge とコールバック先を指定して、顧客の管理者を Devin の接続ページにリダイレクトします。

```
https://app.devin.ai/outposts/connect
  ?callback_url=https://partner.example.com/devin/outpost-callback
  &outpost_name=my-outpost
  &outpost_image=https://partner.example.com/logo.png
  &platform=linux
  &code_challenge=<code_challenge>
```

| Param            | 必須  | 注記                                                                  |
| ---------------- | --- | ------------------------------------------------------------------- |
| `callback_url`   | はい  | Devin が1回限りのコードを送信する先です。許可リストに登録されている必要があります。                       |
| `code_challenge` | はい  | ステップ 1 の PKCE S256 challenge です。                                    |
| `outpost_name`   | いいえ | 推奨されるアウトポスト名です。管理者は確認前に編集できます。                                      |
| `outpost_image`  | いいえ | アウトポストを表す PNG アイコンの URL です。たとえば、貴社のロゴなどです。                          |
| `platform`       | いいえ | 事前選択されるアウトポストのプラットフォームです: `macos`、`linux`、または `windows`。管理者は変更できます。 |

管理者がサインインしていない場合、接続ページはこれらのパラメータを一時保存し、まずサインインを求めたうえで処理を再開します。

<div id="3-admin-confirms">
  ### 3. 管理者による確認
</div>

接続ページには、編集可能なアウトポスト名とプラットフォーム (指定されている場合は `outpost_image` も) を含む確認画面が表示されます。管理者が **Connect** をクリックすると、Devin は権限、コールバックの許可リスト、アウトポスト名が使用可能であることを検証したうえで、暗号化された使い捨てコード (TTL は 10 分) を保存し、1回限りのコードを付けてお客様の app にリダイレクトします。

アウトポスト もサービスユーザーもまだ存在せず、コードが引き換えられたとき (ステップ5) にのみ作成されます。未使用のコードはそのまま期限切れになります。

<div id="4-devin-redirects-the-code-to-your-callback">
  ### 4. Devin がコードをお客様の `callback_url` にリダイレクトします
</div>

ブラウザは、コードが付加された状態でお客様の `callback_url` にリダイレクトされます:

```
https://partner.example.com/devin/outpost-callback?code=<one-time code>
```

<div id="5-exchange-the-code-server-to-server">
  ### 5. サーバー間でコードを交換する
</div>

バックエンドで、ステップ1で保存した`code_verifier`を取得し、トークンエンドポイントに対してコードを引き換えます。これは、フォームエンコードされたOAuth形式のトークンリクエストです。

```bash theme={null}
curl -X POST "https://api.devin.ai/outposts/connection-token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=<one-time code>" \
  --data-urlencode "code_verifier=<code_verifier>"
```

このエンドポイントではDevinの認証は不要です。コードを保持し、対応するPKCE verifierを提示できること自体が証明になります。これは意図的に未認証にしています。コードは使い捨て (一度使用されると原子的に消費される) で、有効期限が短く、お客様のchallengeに紐付けられているためです。

<div id="6-receive-the-credentials">
  ### 6. 認証情報を受け取る
</div>

成功すると、Devin は アウトポスト と、アウトポスト ワーカー を実行するためのスコープを持つサービスユーザーを作成し、次を返します。

```json theme={null}
{
  "outpost_id": "...",
  "account_id": "...",
  "outpost_name": "my-outpost",
  "service_user_id": "...",
  "api_base_url": "https://api.devin.ai",
  "access_token": "cog_...",
  "token_type": "bearer"
}
```

レスポンスには`Cache-Control: no-store`が付与されているため、キャッシュしないでください。

<div id="7-run-outpost-workers">
  ### 7. アウトポスト ワーカーを実行する
</div>

`access_token` と `api_base_url` を安全に保存し、そのトークンを Bearer 認証情報として利用して アウトポスト に対する アウトポスト ワーカーを実行します。

<div id="error-handling">
  ## エラー処理
</div>

トークンエンドポイントは [RFC 6749 §5.2](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2) に従います。不明なコード、期限切れのコード、すでに引き換え済み (replayed) のコード、または PKCE が一致しないコードに対しては、`400` が返されます。

```json theme={null}
{
  "error": "invalid_grant",
  "error_description": "Invalid or expired connection code"
}
```

コードは一度しか使用できず、10分で期限切れになるため、`invalid_grant` は回復不能なエラーとして扱ってください。保存されている `code_verifier` を破棄し、フローをステップ1からやり直してください。

<div id="security-notes">
  ## セキュリティに関する注意事項
</div>

* **トークンがブラウザを経由することはありません。** リダイレクトで中継されるのは使い捨てのコードのみで、サービスユーザーのトークンはサーバー間のやり取りでのみ返されます。
* **PKCE により、コードはあなたに紐付けられます。** あなたのバックエンドだけが保持する `code_verifier` がなければコードは使えないため、リダイレクト (またはコード) を傍受しただけでは引き換えできません。
* **コードは使い捨てで、有効期間も短くなっています。** 引き換え時にコードはその場で消費され、10 分後には失効します。
* **コールバック URL は許可リストに登録されています。** Devin がコードを中継するのは、Cognition があなたの統合向けに事前承認した `callback_url` のみです。
* **そのコードが接続をリクエストしたユーザーのものであることを確認してください。** コールバックに返されたコードが、最初に接続をリクエストしたのと同じユーザーのものであることを確認してください。これにより、攻撃者がユーザーをだまして、気付かないうちに Devin を攻撃者が管理するサンドボックスにバインドさせることを防げます。
* **`outpost_name` は適切な値を指定してください。** 管理者がこれを上書きする場合があり、指定する名前はあくまで提案にすぎません。
