コンテンツにスキップ
HaneDOCSEN

Hane Platform

アーキテクチャ

公開 API への要求がどう処理され、イベントがどう届き、組織と環境のデータがどう分かれるかを製品の視点で説明します。

このページでは、公開 API に届いた要求が処理される流れ、イベントと非同期の処理、組織と環境の分け方を説明します。業務アプリを設計するときに知っておくとよい、Hane の動き方の前提です。

クライアント(業務アプリ・コンソール・hanectl・Hane Cowork)
│ Authorization: Bearer <API キー または アクセストークン>
▼
┌──────────────────────┐
│ 入口(Gateway) │ 資格情報の確認・組織/プロジェクト/環境の確定・レート制限
└──────────┬───────────┘
▼
┌──────────────────────┐
│ 共通 API │ パスで状態の持ち主を選ぶ
└──┬─────────┬─────────┬┘
▼ ▼ ▼
組織の状態 業務データ 監査
(組織ごと) (組織 × 環境ごと) (組織ごと)
│ outbox
▼
キュー ──▶ 監査への追記・メールの送信・webhook の配信・文書の処理
│
▼
永続実行エンジン ──▶ 案件を次の待機か完了まで進める
  1. クライアントは、すべての要求に API キーかアクセストークンを付けます。URL に組織・プロジェクト・環境は入れません。
  2. 入口が資格情報を確かめ、その資格情報に結び付いた組織・プロジェクト・環境を決めます。あわせて、ロールとスコープ、権限の世代、緊急停止の状態を確かめ、レート制限を数えます。この結果を「信頼できる実行コンテキスト」として後ろへ渡し、クライアントが送ったヘッダーの値は信じません。
  3. 共通 API が、パスに応じて状態の持ち主へ要求を渡します。/v1/platform/* は組織の状態、/v1/audit/* は監査、そのほかの業務の API(/v1/data・/v1/definitions・/v1/workflows・/v1/approvals など)は業務データの持ち主です。
  4. 状態の持ち主は、スコープを確かめてから変更を保存します。業務の変更と、それに伴うイベントの記録(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 を足した形で返します

業務データの変更で積んだイベントは、キューを通して非同期に処理します。

  • キューの処理は、まず監査に追記し、それから副作用(メールの送信など)を行います。
  • 配送は「少なくとも 1 回」です。処理する側はイベントの ID で重複を捨てるので、2 回届いても副作用は 1 回です。全体の順序は保証しません。
  • 顧客のシステムへは、購読(event subscription)に登録した宛先へ、署名付きの webhook として届けます。購読と配信は Webhook を参照してください。
  • 文書の検査や本文の取り出しのような重い処理も、業務データの持ち主の外で、キューから動かします。

案件は、日をまたいで人の判断や返信を待つことがあります。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 する

定義の反映と昇格の流れは 定義をコードで管理する で説明します。