GAP / gxai.dev

GAP (GX AI Protocol) Specification v0.1

Status
Draft / リファレンス実装あり
Wire version
gap/0.1
Normative
この日本語版が正典。English version は informative translation
Schema
機械可読スキーマ一式
License
未定(他社実装の可否を保証するものではない)
Source
github.com/kokubee/gxceed@19f2540 · tree a77935e

0. これは何か #

企業のESGデータを、PDFの開示レポートを経由せず、発生源で署名された生の活動量のまま、 API と MCP で投資家のAI Agentに直結するための通信規約。

従来の構造:

基幹システム → 担当者/コンサル(集計・化粧) → PDF報告書 → アナリスト(再入力) → 評価

GAP の構造:

基幹システム/センサー → [署名] → GAP Node → [MCP/REST] → 投資家 AI Agent(算定・検証は受け手側)

名前が指す 3 つの GAP #

GAP中身GAP v0.1 が閉じる手段
Disclosure GAP開示された数値と現場の一次データの乖離発生源の秘密鍵で署名された活動量だけを流通させ、途中の書き換えを数学的に検知可能にする
Time GAP年1回の報告と、投資家のリアルタイムな意思決定の時間軸のズレ追記専用ストリームへの継続的 ingest(Continuous Auditing)。任意の窓を都度算定できる
Agent GAP人間向け非構造化文書と、Agentが要求する決定論的インターフェースの断絶MCP Tool として決定論的な算定・検証を提供。同じ引数なら常に同じ数値とハッシュ

設計上の 1 行 #

GAPは排出量を運ばない。活動量と、それが本物である証拠だけを運ぶ。

排出量は「活動量 × 排出係数」であり、係数の選択は制度・基準・年度によって変わる判断である。 その判断を企業側で先に済ませてしまうことが「化粧」の入口になる。GAP は係数の適用を 受け手側の明示的な選択として分離し、企業側には「測ったもの」だけを出させる。

1. レイヤー構成 #

① セマンティック・データレイヤー(意味の標準化) #

活動量 1 件は次の payload で表現する。これがそのまま署名対象のバイト列になる。

{
  "spec": "gap/0.1",
  "source_id": "jp-demo-plant-chiba-meter-01",
  "seq": 1,
  "metric": "electricity_kwh",
  "period_start": "2026-07-01T00:00:00Z",
  "period_end": "2026-07-01T01:00:00Z",
  "value": 812.4,
  "unit": "kWh",
  "quality": "measured",
  "prev_hash": null,
  "meta": { "line": "A", "tariff": "peak" }
}

スキーマ: reading-payload.schema.json

規定:

  • 時刻は 1 形式のみ: YYYY-MM-DDTHH:MM:SSZ(秒単位・UTC・ミリ秒なし)。 表現ゆれがあると署名バイト列が再現できないため、ミリ秒付きやオフセット表記は仕様違反。
  • quality は必須。推計値・修正値を使うこと自体は正当だが、 ラベルなしで混ぜた瞬間に「化粧していないストリーム」と区別がつかなくなる。
  • seq は source ごとに 1 から連番。欠番は削除・欠測の証跡として残る。
  • Zero-Embellishment Constraint(非化粧制約): metric および meta のキーに派生排出量を示す語 (co2 / co2e / ghg / emission / scope1|2|3 / tco2 / carbon_footprint)を 含む payload は受理してはならない。GAP が運ぶのは活動量に限る。
  • 単位変換・丸め・補正を転送経路で行ってはならない。機器が出した値をそのまま運ぶ。

② クエリ&実行レイヤー(MCP Native) #

投資家側 Agent 向けの MCP Tool(すべて read-only / idempotent):

Tool役割
list_sources一次データ源の発見。呼び出し側の鍵で見える粒度も返す
get_activity_data生の活動量(許可粒度まで)。証跡ハッシュ付き
list_emission_factors適用可能な係数の一覧(出典 URL・公表日つき)
compute_emissions活動量 × 明示指定の係数を決定論的に算定
verify_provenance署名・ハッシュチェーンの再計算(値は返さない
detect_anomalies欠測・seq 欠番・外れ値・フラットライン等の統計的検知

Context Budget Optimization

Agent のコンテキストは「数値 + それが正しい根拠」に使わせ、生ログの運搬には使わせない。

  • 応答点数は上限(既定 1000 点)で頭打ちにし、超えたら黙って切り詰めず too_many_points を返して粒度を粗くさせる。
  • verify_provenance は真偽値とハッシュのみを返す(値を運ばずに正しさだけを運ぶ)。
  • 集計して返す場合も bucket_hash(内訳 payload_hash の SHA-256)を添え、 値を明かさずに「どの生データから作ったか」を検証可能にする。

算定ロジックの責任の所在

compute_emissions は係数を一意に特定できないと数値を返さない。 候補が複数あれば factor_ambiguous として候補一覧を返す。 これは実装の不便さではなく仕様である — ノードが暗黙に係数を選べてしまうと、 「誰の判断でこの数値になったのか」が再び曖昧になる。

③ トラスト&アイデンティティレイヤー(証明と権限) #

正規化: RFC 8785 のサブセット。オブジェクトのキーは昇順、空白なし、 非有限数は禁止、-00 に正規化。

ハッシュ: payload_hash = SHA-256(canonical_json)(hex 小文字)

チェーン: prev_hash が直前 reading の payload_hash を指す追記専用リンク。 seq は 1 ずつ増加。過去の差し替え・こっそりした削除はリンク切れとして露見する。

署名: Ed25519。canonical JSON の UTF-8 バイト列に対する署名を base64 で付す。 公開鍵は source 登録時にノードへ渡す(fingerprint = SHA-256 が公開される)。

検証の再計算義務: ノードは ingest 時の検証結果フラグを信用してはならない。 compute_emissions算定の直前に署名とハッシュを取り直し、 1 件でも不整合があれば数値を返さず provenance_compromised を返す。 (ingest 時のフラグだけを信じる実装は、ノードのストレージを直接書き換えられた場合に 「検証済み」と称して化粧後の数値を配ってしまう。)

Granular Access Control(機密境界)

disclosure_level誰が読めるか粒度
public承認済みの全 API keymin_bucket_seconds まで粗くして開示(例: 時間計測 → 日次開示)
engagementraw_access_grants を持つ鍵のみgrant 側でより細かい粒度を許可可能
restrictedノード内部のみ

工場のリアルタイム電力は生産稼働率・原価に直結する機密になり得る。 GAP は「隠す / 全部見せる」の二択にせず、時間粒度を落として開示し、 落とした後も検証可能性を保つbucket_hash)ことで折り合いをつける。 engagement の source は grant がない鍵にも存在だけは見せるaccess.granularity = "none")。隠すとエンゲージメントの入り口が消えるため。

2. エンドポイント #

メソッドパス認証
GET/.well-known/gap.jsonなし(ノード発見)
GET/api/v1/gap/schemaなし(JSON Schema バンドル)
GET/api/v1/gap/sources[/:id[/readings]]API key
GET/api/v1/gap/factorsAPI key
GET/api/v1/gap/computeAPI key
GET/api/v1/gap/verifyAPI key
GET/api/v1/gap/anomaliesAPI key
POST/mcp/gapAPI key(MCP Streamable HTTP)
GET/api/gap/ingest/headノード発行の ingest bearer
POST/api/gap/ingestingest bearer + reading ごとの Ed25519 署名

ingest の認証が 2 段なのは、トークンが漏れても過去の書き換えはできないようにするため。 トークンは「誰が接続してよいか」、署名は「そのデータが本物か」を担保する。

3. エラー(規定) #

code意味
embellishment_rejected派生排出量を含む payload(非化粧制約違反)
signature_invalid登録鍵で検証できない
chain_broken / seq_out_of_orderチェーン先端に繋がらない
provenance_compromised保存済みデータが署名と一致しない(算定を拒否)
factor_ambiguous係数が一意に定まらない(候補を同梱)
factor_not_found / unit_mismatch / factor_metric_mismatch係数の選択が不正
granularity_denied開示粒度より細かい要求
grant_required / source_restricted開示範囲外
too_many_points / window_too_large応答が上限超過(粒度か窓を変える)

バッチ ingest は all-or-nothing。1 件でも壊れていれば全体を拒否し、 受理も拒否も監査ログ(raw_ingest_log)に残す。

4. リファレンス実装 #

リファレンス実装は非公開リポジトリ kokubee/gxceed にあり、現時点で外部からは参照できない。 以下のパスは実装の構成を示すためのもので、リンクではない。

場所内容
workers/data-api/src/raw/provenance.ts正規化 / ハッシュ / チェーン / 署名検証
workers/data-api/src/raw/ingest.ts署名検証つき ingest(非化粧制約の実装)
workers/data-api/src/raw/store.ts参照・集計・算定・検証・異常検知
workers/data-api/src/mcp-gap.tsMCP Server(6 tools + spec resource)
workers/data-api/src/routes/gap.tsREST バインディング(MCP と同一ロジック)
scripts/gap/gap-sign.mjs発生源側の署名ライブラリ(依存なし・Node 22)
scripts/gap/demo-factory-meter.mjs工場スマートメーターのデモデータ生成
scripts/gap/e2e-local.mjsローカル一気通し(32 チェック)
scripts/health/gap-selftest.mjs正規化・ハッシュ・署名のテストベクタ検証
node scripts/health/gap-selftest.mjs   # 証跡レイヤーの自己診断
node scripts/gap/e2e-local.mjs         # 署名 → ingest → 算定 → 検証 → MCP を一気通し

テストベクタは test-vectors.json。 署名鍵は RFC 8032 §7.1 TEST 1 の公開テスト鍵で、実運用には使えない値を意図的に使っている。

5. v0.1 の意図的な非対応(v0.2 以降の論点) #

  • Zero-Knowledge Proof / 差分プライバシー: 現状の機密対応は時間粒度の粗視化まで。 「生データを明かさずに正当性のみ証明する」までは踏み込んでいない。
  • 鍵ローテーションの手続き: public_key_hash を reading に記録しており 過去分の再検証はできるが、ローテーション自体のプロトコルは未定義。
  • 複数ノード間のクロス検証: input_hash により同一入力からの同一結果は照合できるが、 ノード間の相互監査プロトコルはない。
  • Scope 3 / サプライチェーン連鎖: 他社ノードの活動量を参照する連鎖構造は未定義。 現状は 1 ノード内の source に閉じる。
  • ストリーミング購読: 現状はポーリング。webhook / SSE による push は未定義。
  • 制度マッピング(CSRD / SSBJ / GHG Protocol): GAP は活動量と係数を分離するだけで、 どの制度のどの項目に対応するかの写像は持たない。写像は受け手側の責務とする。

6. 標準としての狙い #

個別企業がばらばらの MCP を実装すると、投資家側 Agent の統合コストが企業数に比例して増える。 GAP が固定しようとしているのは以下の 4 点だけで、それ以外は各社の自由に任せる:

  1. 署名対象のバイト列(正規化規則)
  2. チェーンの張り方(prev_hash + seq
  3. Tool の名前と入出力の意味(6 tools)
  4. 「排出量ではなく活動量を出す」という制約

この 4 点が揃っていれば、投資家側の 1 つの Agent 実装が、 どの企業の GAP Node に対しても同じコードで接続・検証・横断比較できる。

機械可読スキーマ #

各スキーマの $id はこのサイトの URL を指しており、$ref もここで解決する。 配布物の由来と各ファイルの SHA-256 は manifest.json にある。

ファイル役割
reading-payload.schema.json署名の単位。正規化したこのオブジェクトがハッシュ・署名対象のバイト列そのもの
ingest-request.schema.json発生源からノードへ送るバッチのエンベロープ
source.schema.jsonデータ源の公開記述子(何を・どの頻度で・どの鍵で・どの開示粒度で)
emission-factor.schema.json出典を辿れる係数。署名対象のストリームの外に意図的に置く
compute-result.schema.json算定結果の形。独立に再現するのに要る情報を含む
test-vectors.json正規化・ハッシュ・チェーン・署名のベクタ

正規化・ハッシュ・チェーン規則を変更すると、このバージョンで作られた署名がすべて無効になる。 その種の変更はここへの編集ではなく、新しい spec 値(v0.2)を要する。