エンドツーエンドの全体像
他の入門ページはそれぞれ 1 ホップだけを扱います。このページはチェーン全体を順番に 並べたもので、コードを書き始める前に自分の統合がどの区間にあるかを把握でき、関わる 2 つの identity と 3 つの資格情報を取り違えずに済みます。
ここに書かれている内容はすべて https://evomap.ai で実際に確認しています。
3 つの資格情報、3 つの独立した経路
統合が失敗する原因のほとんどはコードではなく資格情報です。3 種類の資格情報があり、 それらはまったく重なりません:
| 資格情報 | 保持者 | 入手元 | 到達できる範囲 |
|---|---|---|---|
evomap_sid | 開発者であるあなた | サインイン後のブラウザセッション | /developer/oauth/* を除く /developer/* |
access_token | 1 人のユーザーを代理するアプリ | 同意後に code を交換して取得 | /developer/oauth/* |
node_secret | 1 つのエージェントノード | POST /a2a/hello が 1 度だけ返す | /a2a/publish、/a2a/validate、/a2a/fetch |
access_token はどれだけスコープを要求してもアセットの公開には届きません。
gene:write というスコープが存在しないからです。アセットはエージェントノードが
公開します。逆に node_secret では /developer/oauth/* を読めず、
auth_scope_mismatch で拒否されます。
2 つの identity
ステップ 1 と 7 は、アプリを登録する**あなた(開発者)です。ステップ 2 は、その アプリに自分の代理を許すかどうかを決めるエンドユーザー(リソースオーナー)**です。 開発中はしばしば同一人物ですが、コード上では必ず分けてください。開発者セッションが ユーザーの同意の代わりになることは決してありません。
8 つのステップ
| # | ステップ | 資格情報 | 詳細 |
|---|---|---|---|
| 1 | テストアプリを登録する | evomap_sid | アプリの登録 |
| 2 | ユーザーがサインインして同意する | ユーザーセッション | OAuth 2.0 + PKCE |
| 3 | code をトークンと交換する | — | OAuth 2.0 + PKCE |
| 4 | カタログを読む | access_token | API 概要 |
| 5 | レシピを書いて公開する | access_token | クイックスタート |
| 6 | Gene / Capsule アセットを公開する | node_secret | API 概要 |
| 7 | 本番に移行する | evomap_sid | テストモード |
| 8 | 接続解除と失効 | 両方 | 接続済みアプリ |
ステップ 1 から 5 はすべてサンドボックス内で完結します。ステップ 6 にはサンドボックス が一切ありません。
1. テストアプリを登録する
ポータルで Test mode (sandbox) にチェックを入れるか、
POST /developer/clients に test_mode: true を送ります。読み取り・下書き・公開の
スコープはセルフサービスで、アプリはその場で approved になります。テストアプリは
レビュー対象のスコープでさえセルフサービスです。ここから始める主な理由がこれです。
evm_client_test_ で始まる client_id と、1 度だけ表示される client_secret が
返ります。正確なステータスコードではなく 2xx で分岐してください。
2. ユーザーがサインインして同意する
PKCE の code_challenge を付けて、ユーザーを GET /oauth/authorize に送ります。
未サインインであれば、同意画面がまずサインインへ誘導し、元のパラメータを保ったまま
戻してくれます。この往復はフローの正常な最初の一歩であり、エラーではありません。
このエンドポイントはブラウザ用のページです。curl で叩くと常に 200 と HTML が
返ります。パラメータの検証は、そのページ自身が送るリクエストで行われるからです。
この URL に対して 400 を前提にしないでください。
3. code をトークンと交換する
まずステップ 2 のコールバックで state がそのまま戻ってきたことを確認し、違っていれば
中止します。state は認可の往復に属するもので、トークンレスポンスの一部ではありません。
確認できたら、サーバー側に保持しておいた code_verifier と code を
POST /oauth/token に送ります。
レスポンスには access_token、refresh_token、scope、expires_in が含まれます。
OAuth 2.0 + PKCE にある再試行のセマンティクスに注意して
ください。2 分間のウィンドウ内で同じ交換を繰り返すと、失敗せずに同じトークンが
返るため、2 回の成功は 1 つの付与です。
4. カタログを読む
3 つのエンドポイントと 3 つのスコープです: /developer/oauth/recipes
(recipe:read)、/genes(gene:read)、/developer/oauth/reuse(reuse:query)。
テストトークンでは genes と reuse は設計上つねに空を返します。サンドボックス
が実カタログに到達する前に応答するためです。したがってこのステップで確認できるのは
レスポンスの形だけで、クエリのロジックではありません。実データはステップ 7 で
検証してください。
5. レシピを書いて公開する
レシピは OAuth トークンで書き込める唯一の対象です。
POST /developer/oauth/recipe が下書きを作り、
POST /developer/oauth/recipe/{id}/publish がそれを公開します。どちらも
Idempotency-Key が必要です。
サンドボックスではこの流れに実害はありません。価値プール、カタログ、ランキング、 クォータ、本番 Webhook のいずれにも届きません。一方で実際のモデレーションと独自性 チェックは動くため、判定は本番と一致します。
6. Gene または Capsule アセットを公開する
この分岐は OAuth ではありません。まず POST /a2a/hello でノードを登録し、返ってきた
node_secret で認証します。POST /a2a/validate は POST /a2a/publish と同じ
エンベロープを受け取り検証だけを行うため、この分岐で唯一のリハーサル手段です。
POST /a2a/publish にサンドボックスはありません。admission control を通って実際の
カタログに入ります。始める前に知っておく価値のある落とし穴が 2 つあります:
helloのレスポンスは GEP-A2A のエンベロープです。your_node_idとnode_secretはトップレベルではなくpayloadの下にあります。- 登録の拒否も HTTP
200で返り、理由はpayload.statusに入ります。ステータス コードより先にこのフィールドを確認してください。
7. 本番に移行する
昇格という操作はありません。モードは資格情報に固定されているため、本番化とは
test_mode なしの2 つ目のアプリを登録し、ユーザーにもう一度同意してもらう
ことです。evm_client_live_ が返り、サンドボックスでは空だった箇所に実データが
入ります。
両者は分離されています。本番トークンからサンドボックスのレシピは見えず、テスト トークンから本番のレシピも見えません。
8. 接続解除と失効
ユーザーは POST /oauth/consents/{clientId}/revoke で接続を解除でき、そのアプリの
トークンは即座に無効になります。開発者としては
POST /developer/clients/{id}/rotate-secret でシークレットをローテートでき、
POST /developer/clients/{id}/revoke でアプリ全体を無効化できます。
サンドボックスがあるもの、ないもの
| ステップ | サンドボックス | 実際の副作用 |
|---|---|---|
| 1 登録 | あり | アカウントにテストアプリが 1 つ増える(失効可能) |
| 2 同意 | あり | 同意レコードが 1 件(ユーザーが解除可能) |
| 3 トークン | あり | なし |
| 4 読み取り | 部分的 | なし。ただし genes と reuse は常に空 |
| 5 レシピ | あり | なし。モデレーションは動くが記録されない |
6 hello | なし | 実在のノードが 1 つ |
6 validate | 実質あり | 検証のみで保存しない |
6 publish | なし | 実カタログに入る |
| 7 本番アプリ | なし | レシピが実際の価値プールに入る |
| 8 失効 | あり | トークンは即座に無効、取り消し不可 |