Hane Platform
アーキテクチャ
公開 API への要求がどう処理され、イベントがどう届き、組織と環境のデータがどう分かれるかを製品の視点で説明します。
このページでは、公開 API に届いた要求が処理される流れ、イベントと非同期の処理、組織と環境の分け方を説明します。業務アプリを設計するときに知っておくとよい、Hane の動き方の前提です。
クライアント(業務アプリ・コンソール・hanectl・Hane Cowork) │ Authorization: Bearer <API キー または アクセストークン> ▼ ┌──────────────────────┐ │ 入口(Gateway) │ 資格情報の確認・組織/プロジェクト/環境の確定・レート制限 └──────────┬───────────┘ ▼ ┌──────────────────────┐ │ 共通 API │ パスで状態の持ち主を選ぶ └──┬─────────┬─────────┬┘ ▼ ▼ ▼ 組織の状態 業務データ 監査 (組織ごと) (組織 × 環境ごと) (組織ごと) │ outbox ▼ キュー ──▶ 監査への追記・メールの送信・webhook の配信・文書の処理 │ ▼ 永続実行エンジン ──▶ 案件を次の待機か完了まで進める- クライアントは、すべての要求に API キーかアクセストークンを付けます。URL に組織・プロジェクト・環境は入れません。
- 入口が資格情報を確かめ、その資格情報に結び付いた組織・プロジェクト・環境を決めます。あわせて、ロールとスコープ、権限の世代、緊急停止の状態を確かめ、レート制限を数えます。この結果を「信頼できる実行コンテキスト」として後ろへ渡し、クライアントが送ったヘッダーの値は信じません。
- 共通 API が、パスに応じて状態の持ち主へ要求を渡します。
/v1/platform/*は組織の状態、/v1/audit/*は監査、そのほかの業務の API(/v1/data・/v1/definitions・/v1/workflows・/v1/approvalsなど)は業務データの持ち主です。 - 状態の持ち主は、スコープを確かめてから変更を保存します。業務の変更と、それに伴うイベントの記録(outbox)は 1 つのトランザクションで書くので、「データは変わったがイベントが出ていない」状態は起きません。
書込みの API には、次の共通の決まりがあります。詳しくは各サービスのページと API リファレンス を参照してください。
| 決まり | 内容 |
|---|---|
| 冪等性 | 副作用のある POST には Idempotency-Key を付けます。同じキー・同じ内容の再送には最初の応答を返し、内容が違えば 409 IDEMPOTENCY_CONFLICT です。SDK は付け忘れると自動で付けます |
| 楽観的排他 | 変更できる資源は version を持ちます。更新には取得したときの ETag を If-Match で送ります。欠けていれば 428、合わなければ 412 です |
| エラー | RFC 9457 の Problem Details に code・request_id・retryable を足した形で返します |
イベントと非同期の処理
Section titled “イベントと非同期の処理”業務データの変更で積んだイベントは、キューを通して非同期に処理します。
- キューの処理は、まず監査に追記し、それから副作用(メールの送信など)を行います。
- 配送は「少なくとも 1 回」です。処理する側はイベントの ID で重複を捨てるので、2 回届いても副作用は 1 回です。全体の順序は保証しません。
- 顧客のシステムへは、購読(event subscription)に登録した宛先へ、署名付きの webhook として届けます。購読と配信は Webhook を参照してください。
- 文書の検査や本文の取り出しのような重い処理も、業務データの持ち主の外で、キューから動かします。
長く続く業務
Section titled “長く続く業務”案件は、日をまたいで人の判断や返信を待つことがあります。Workflow の解釈と案件・待機の状態は業務データの持ち主が持ち、ステップを進める処理は永続実行エンジンが受け持ちます。待機に入ると実行はいったん終わり、Task の完了やイベントの到着で新しく再開します。待っている間に LLM を呼び続けたり、Agent の CLI を動かし続けたりはしません。詳しくは Workflow と案件 を参照してください。
Agent の CLI は、ネットワークを閉じたサンドボックスのコンテナで動き、Hane が用意したツールの口を通してだけ業務に触れます。詳しくは Agent を参照してください。
Hane は Cloudflare のグローバルネットワーク上で動きます。業務アプリから意識する必要はありませんが、性質を知っておくと設計の判断に役立ちます。
| 使っているもの | Hane での役割 |
|---|---|
| Workers | 入口と共通 API。要求ごとに起動し、状態を持たない |
| Durable Objects | 組織の状態・業務データ・監査の持ち主。それぞれが自分の SQLite を持ち、要求を 1 つずつ順に処理するので、同じ持ち主の中の書込みはトランザクションで守られる |
| D1 | 組織をまたぐ索引(組織の名前、API キーのハッシュ、利用者の所属と招待) |
| R2 | 文書の原本、ReleaseBundle の本文、監査の記録の本体 |
| Queues | イベントの配送、文書の処理、webhook の配信。届かなかったものは dead letter queue に残る |
| Workflows | 案件を進める永続実行エンジン |
| Containers | Agent の CLI のサンドボックスと、文書の変換・OCR のような使い捨ての処理 |
組織ごとのデータの分離は、データの置き場所そのものを分けることで行います。
- 業務データの持ち主は「組織 × 環境」ごとに 1 つです。ほかの組織のデータと同じデータベースに入ることはありません。
- 組織の情報(メンバー、グループ、プロジェクト、サービスアカウント、緊急停止)は、組織ごとに 1 つの持ち主に置きます。
- どの持ち主に渡すかは、入口が確かめた実行コンテキストからだけ決めます。要求の本文やヘッダーから決めることはありません。
- プロジェクトは、同じ持ち主の中のキーと認可で分けます。どの表もプロジェクトの ID をキーに持ち、読み書きは必ず今のプロジェクトに絞ります。
1 つのプロジェクトは dev・stage・prod の 3 つの環境を持ちます。
| 項目 | 環境ごとの扱い |
|---|---|
| 業務データ | 環境ごとに別の持ち主に置く。dev と prod のデータが混ざることはない |
| 資格情報 | サービスアカウントと API キーは、1 つのプロジェクトの 1 つの環境に結び付く。アクセストークンも組織・プロジェクト・環境を決めて発行する |
| 定義 | apply できるのは dev だけ。dev で作った ReleaseBundle を、同じ中身のまま stage・prod へ昇格させる |
| 設定 | 環境ごとに違う値(接続先や送信元など)は、環境ごとの EnvironmentBinding に書き、その環境で apply する |
定義の反映と昇格の流れは 定義をコードで管理する で説明します。