透明性ログでAccess Transparencyイベントを検証する
Compliance APIの署名付きチェックポイントとMerkle証明を使用して、Access Transparencyイベントがログにコミットされた後に削除または改ざんされていないことを検証します。
Access Transparencyイベントが組織の透明性ログにコミットされた後に削除または改ざんされていないことを、暗号学的に検証する方法を説明します。
透明性ログの仕組み
「transparency log」(透明性ログ)は、記録を改ざん検知可能にするための手法です。エントリは追記されるだけです。ログが拡大するたびに、その運営者は「checkpoint」(チェックポイント)と呼ばれる短いステートメントに署名します。チェックポイントは、Merkleツリーハッシュを通じて、それまでのすべてのエントリにコミットします。チェックポイントを保持している人は誰でも、後から、現在のログがそのチェックポイントでカバーされていたすべてのものを、変更なく同じ順序で依然として含んでいることの証明を要求できます。したがって、エントリの削除や書き換えは、そのエントリをカバーするチェックポイントを保持している検証者に必ず気付かれます。Certificate TransparencyやGoモジュールのチェックサムデータベースも同じ手法に基づいて構築されています。C2SP tlog-tilesは、このようなログを署名付きチェックポイントと、ハッシュおよびエントリの静的でキャッシュ可能なタイルとして提供するためのオープンな仕様であり、クライアントはハッシュを取得してすべての証明を自分で計算できます。
Access Transparencyが有効になると、Anthropicは組織の透明性ログを維持します。これは、Access Transparencyイベント(anthropic_accessおよびcmek_preserve)の追記専用で暗号学的に署名された記録です。ログの作成後に組織で記録されたこのようなイベントはそれぞれ、ログに追記されます。ログはC2SP tlog-tiles形式に従っているため、この標準向けに構築されたツールはそのチェックポイント、タイル、証明を理解できます。
- 組織ごとに1つのログ。 各組織のログには固定のオリジン文字列
axt.anthropic.com/<your organization UUID>があります。オリジンは組織が存続する限り変わりません。 - すべての新しいイベントがリーフになります。 Access TransparencyイベントがActivity Feedに表示される対象になると、まずリーフとしてログに追記され、その後にのみフィードで提供されます。リーフは、イベントのドキュメント化されたフィールドの決定論的なシリアライズです。フィード上のイベントには、ログ内でのゼロベースの位置である
transparency_log_leaf_indexが含まれます。 - チェックポイントは履歴全体にコミットします。 ログはMerkleツリーです。ログが拡大するたびに、Anthropicは署名付きチェックポイントを公開します。これは、ログのオリジン、現在のサイズ、およびすべてのリーフにコミットするルートハッシュを記載した短いテキストドキュメントです。各チェックポイントには、ログの署名鍵による署名がちょうど1つ含まれます。
- これにより2種類の証明が可能になります。 「inclusion proof」(包含証明)は、特定のイベントがチェックポイントの下でその位置に存在することを示します。「consistency proof」(一貫性証明)は、後のチェックポイントが、保存しておいた以前のチェックポイントの追記専用の拡張であり、その間で何も削除または変更されていないことを示します。
- 検証鍵はインバンドで提供されます。 検証鍵エンドポイントは、チェックポイントに署名する公開鍵を返します。計画的な鍵のローテーションでは、新しい鍵は署名を開始する前にそのリストに追加され、以前の鍵もリストに残ります。そのため、すでに保持しているチェックポイントは引き続き検証できます。
透明性ログが証明すること
- 保持しているイベントのリーフフィールド(イベントがリーフになる仕組みに記載)が、Anthropicがログにコミットしたものとバイト単位で一致すること。
- 組織のログは拡大するだけであること。ログにコミットされたイベントが後でそこから削除または書き換えられた場合、保持しているチェックポイントに対する検証は失敗します。また、以前に提供されたものとは異なる履歴が提供された場合にも失敗します。
- 新しいエントリは追記のみ可能であること。すでに検証した履歴にイベントを挿入することはできません。
証明しないこと、変更しないこと
- すべてのアクセスが記録されたこと、または記録されたイベントがアクセスを正確に説明していることは証明しません。証明するのは、Anthropicがログにコミットしたものがそれ以降変更されていないことだけです。
- Access Transparencyの対象範囲やイベントが届くタイミングは変更しません。
workspace_uuidや後から追加されるフィールドなど、リーフ外で提供されるフィールドは証明の対象外です。- 包含証明は、提供されたイベントについて述べるものです。それ自体では、フィードがログに含まれるすべてのリーフを一覧表示したことは証明しません。ログのエントリバンドルにはすべてのリーフが含まれているため、必要に応じてコミットされたイベントの完全なセットを直接読み取ることができます。
- イベントに
transparency_log_leaf_indexが存在することはポインタであり、証明ではありません。イベントをログにコミット済みとして扱う前に、必ず包含を検証してください。 - 書き換えられた履歴に対する保護は、保持しているチェックポイントから得られます。公開されている鍵フィンガープリントに記載された鍵によるチェックポイントの署名は、それがAnthropicのログから来たことを証明します。前回保存したチェックポイントからの一貫性証明は、すでに観測した履歴が拡大しただけであることを証明します。
始める前に
以下が必要です。
read:compliance_activitiesスコープを持つCompliance Access Key。これはActivity Feedで使用するのと同じキーとスコープです。親組織のキーは、すべてのリクエストで子組織を指定することで、登録済みの各子組織のログを読み取ることができます。- 組織のUUID。Claude ConsoleのSettings > Organizationで確認できます。これはActivity Feedが
organization_uuidとして提供するのと同じ値ですが、Consoleから取得してください。この値こそがチェックポイントをあなたのものにするため、検証対象のAPIから取得してはいけません。ログのオリジンは、この値からaxt.anthropic.com/<organization UUID>として導出します。この文字列は自分で導出してください。APIレスポンスから読み取らないでください。 - 最後に検証したチェックポイントを保持しておく永続的な保存場所。保存したチェックポイントこそが、「ログは今日一貫している」を「ログは監視を始めて以来一貫している」に変えるものです。
タイミング
- イベント: Access Transparencyイベントは、アクセスから2営業日以内にActivity Feedに表示されます。イベントは提供対象になって初めてログに入るため、ログがイベントを早期に明らかにすることはありません。ログはフィードがイベントを提供する前に書き込まれるため、エントリがフィードにイベントが表示される前に短時間ログに表示されることがあります。この差は不一致ではありません。
- チェックポイント: ログが拡大するたびに新しいチェックポイントが公開されます。
- 包含証明: 新しく提供されたイベントの証明は、イベントの位置をカバーするチェックポイントが公開されると利用可能になります。通常はイベントが表示された直後です。それより早くリクエストした場合は
404を受け取るため、少し待ってから再試行してください。 - 検証の頻度: 検証は少なくとも毎日実行してください。1時間ごとが妥当です。
- 登録解除: 組織がAccess Transparencyの使用を停止しても、何も削除されません。ログは同じエンドポイントを通じて引き続き読み取り可能です。後でAccess Transparencyが再度有効になった場合、同じログが継続されます。
保持と削除
- 透明性ログ: Anthropicはログからエントリを削除せず、ログに有効期限はありません。エントリの削除こそがログが検出するために存在する変更であるため、組織がAccess Transparencyの使用を停止した場合や組織が削除された後も保持されます。エントリバンドルには各イベントのリーフフィールドが含まれるため、これらのフィールドはログと同じ期間保持されます。
- Activity Feed: Activity Feed上のAccess Transparencyイベントは、フィードの保持期間に従います。アクティビティは6年間保持されます。アクティビティフィードをクエリするを参照してください。
- お客様による削除不可: 透明性ログエンドポイントは読み取り専用です。エントリを削除または修正する方法はありません。
透明性ログエンドポイント
https://api.anthropic.com/v1/compliance/transparency_log/の下で、6つの読み取り専用エンドポイントが提供されています。
| エンドポイント | 返すもの |
|---|---|
GET /checkpoint | 最新の署名付きチェックポイント |
GET /keys | 検証鍵セット |
GET /inclusion | 1つのイベントの包含証明 |
GET /consistency | 保持しているチェックポイントから最新のチェックポイントへの一貫性証明 |
GET /tile/{level}/{index} | Merkleハッシュタイル |
GET /tile/entries/{index} | リーフバイトのエントリバンドル |
チェックポイント、タイル、エントリバンドルは、C2SP tlog-tilesのワイヤ形式に厳密に従います。2つの証明エンドポイントは利便性のためのものです。すべての証明はタイルからも計算できるため、証明エンドポイントの出力を信頼する必要はありません。返されたハッシュを署名付きチェックポイントに対して検証します。
認証とスコープ
すべてのCompliance APIリクエストと同様に、Compliance Access Keyをx-api-keyヘッダーで送信し、anthropic-versionヘッダーも送信します(バージョニングを参照してください)。組織でCompliance APIが有効になっている必要があります。
透明性ログ専用の権限はありません。組織またはその親組織のActivity Feedを読み取れるキーであれば、エントリバンドル内のイベントフィールドを含め、ログ全体を読み取ることができます。
すべてのリクエストは、ちょうど1つの組織のログを読み取ります。
- 組織レベルのキーは、自身の組織のログを読み取ります。
organization_idクエリパラメータは省略可能です。指定する場合は、キー自身の組織を指定する必要があります。 - 親組織レベルのキーは、1つの子組織を指定する
organization_idを渡す必要があります。 organization_idは、org_...タグ付きIDまたは組織UUIDを受け付けます。
404は、このキーで読み取れるログが存在しないことを意味します。キーのスコープ外の組織、存在しない組織、ログがまだ作成されていない組織は、意図的に区別できないようになっています。その後Access Transparencyの使用を停止した組織のログはこのケースに該当しません。引き続き提供されます。
エラー
エラーは、テキストおよびバイナリのエンドポイントを含むすべてのエンドポイントで、標準のCompliance API JSONエラーエンベロープを使用します。エンベロープと共通のエラータイプについては、エラーを参照してください。
| ステータス | このサーフェスでの意味 |
|---|---|
400 | organization_idの形式が不正であるか親組織のキーで省略されている、Compliance APIが有効になっていない、クエリパラメータが不明である、またはエンドポイントごとの検証に失敗した |
401 | APIキーがないか有効ではない |
403 | キーに必要なスコープがない |
404 | このキーで読み取れるログがない、またはエンドポイントごとの「カバーされていない」および「ツリーの範囲外」のケース |
429 | レート制限されています。これらのエンドポイントは、Compliance APIの親組織ごとのレート制限を共有します。retry-afterに従ってください |
503 | ログが一時的に利用できません。バックオフを使用して再試行してください |
キャッシング
レスポンスは、リクエストしたクライアントのみがキャッシュできます。Cache-Controlには常にprivateが含まれ、レスポンスにはVary: x-api-keyが付与されます。これらのエンドポイントの前に共有キャッシュを置かないでください。完全なタイルと完全なエントリバンドルは変更されることがなく、Cache-Control: private, max-age=604800, immutableで提供されます。チェックポイント、証明、鍵、部分タイル、エラーを含むその他すべては、Cache-Control: private, no-storeで提供されます。
最新のチェックポイントを読み取る
GET /v1/compliance/transparency_log/checkpoint
curl --fail-with-body -sS \
"https://api.anthropic.com/v1/compliance/transparency_log/checkpoint" \
--header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
--header "anthropic-version: 2023-06-01"レスポンスはtext/plainで、C2SPの署名付きノートです。本文の行は、オリジン、10進数のツリーサイズ、base64のルートハッシュです。その後に空行が続き、次に署名行が続きます。署名行はemダッシュ(U+2014)で始まり、オリジンを示し、base64の値で終わります。ここでの値は例示です。
axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b
1207
C6C4HzGRqDNlbu54LWCvpDX0NcB5DRTmLcjM4u5vWUI=
— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBFAiEAvL8m…(base64)…- デコードされた署名値の最初の4バイトは署名鍵の
key_hashであり、検証鍵セットのどのエントリで検証するかを示します。残りのバイトは、ノート本文(本文の末尾の改行を含む、空行より前のすべてのバイト)のSHA-256に対するASN.1 DER ECDSA P-256署名です。 - チェックポイントには、ルートハッシュの後に追加の行が含まれる場合があります。理解できない行は無視してください。それらは署名の対象に含まれています。
- 名前がオリジンと一致しない署名行、または保持していない鍵ハッシュの署名行は無視してください。
- チェックポイントは決してキャッシュしないでください。古いチェックポイントはログの現在のサイズを隠してしまうため、新しく提供されたイベントがカバーされていないように見えます。
検証鍵を読み取る
GET /v1/compliance/transparency_log/keys
curl --fail-with-body -sS \
"https://api.anthropic.com/v1/compliance/transparency_log/keys" \
--header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
--header "anthropic-version: 2023-06-01"{
"type": "transparency_log_keys",
"origin": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b",
"log_keys": [
{
"verifier_key": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b+<key_hash>+<base64 key>",
"key_hash": "<8 lowercase hex digits>",
"fingerprint": "<64 lowercase hex digits>",
"algorithm": "ecdsa_p256_sha256",
"public_key": "<base64 DER SubjectPublicKeyInfo>"
}
]
}| フィールド | 型 | 説明 |
|---|---|---|
type | string | 常にtransparency_log_keys |
origin | string | このログのすべてのチェックポイントに含まれるオリジン行。情報提供用です。チェックポイントはこのフィールドではなく、自分で導出したオリジンと比較してください |
log_keys | array | 新しいチェックポイントに署名する鍵が最初に来て、その後にログが提供する他のすべての鍵が新しい順に続きます。空になることはありません |
log_keys[].verifier_key | string | C2SPのnote-verifier文字列<origin>+<key_hash>+<base64 key>としての鍵。ECDSAノート鍵をサポートするtlog-tilesツール(たとえば、Goのgithub.com/transparency-dev/formatsモジュール)で受け付けられます。base64部分をデコードすると、アルゴリズムバイト0x02の後にDERエンコードされた公開鍵が続きます |
log_keys[].key_hash | string | 8桁の小文字16進数。この鍵をチェックポイントの署名行と照合する4バイトのセレクタです。fingerprintの最初の4バイトであり、識別子ではありません |
log_keys[].fingerprint | string | 64桁の小文字16進数:DER SubjectPublicKeyInfoのSHA-256 |
log_keys[].algorithm | string | 鍵の種類。現在はecdsa_p256_sha256です。値が追加される可能性があります。サポートしていないアルゴリズムの鍵はスキップしてください |
log_keys[].public_key | string | base64 DER SubjectPublicKeyInfoとしての公開鍵 |
key_hashは鍵のバイトのみを対象とします。これはDER SubjectPublicKeyInfoに対するSHA-256の最初の4バイトであり、ECDSA note-verifierエンコーディングが使用するルールです。基本の署名付きノート形式がEd25519鍵に対して定義する名前依存の鍵IDではないため、オリジンによって変わることはありません。公開されている鍵フィンガープリントに記載された鍵による有効な署名は、チェックポイントがAnthropicの透明性ログサービスから来たことを証明します。署名付きチェックポイント内のオリジン行こそが、それを組織に結び付けるものです。そのため、その行を自分で導出したオリジンと比較します。
鍵はローテーションされる場合があります。
- ローテーションは切り替えです。あるチェックポイント以降、新しいチェックポイントは新しい鍵で署名されます。
- 計画的なローテーションでは、新しい鍵は何かに署名する前に
log_keysに表示され、以前の鍵もリストに残ります。そのため、ローテーション前に保存したチェックポイントは引き続き検証できます。 - 検証者は、実行のたびに鍵セットを取得することも、ローカルに保持することもできます。ローカルに保持する検証者は、保持していない
key_hashの署名に遭遇したときにこのエンドポイントを再度読み取ります。
公開されている鍵フィンガープリント
Anthropicは、チェックポイントに署名するすべての鍵のフィンガープリントを、API外のこのページで公開しています。これにより、ローカルに保持している鍵を、提供経路では改変できないソースと照合できます。保持している鍵は、以前のGET /keysレスポンスから取得したものか、鍵をピン留めするツールから取得したものである場合があります。
| 鍵ハッシュ | SHA-256フィンガープリント | アルゴリズム | 署名開始日 | ステータス |
|---|---|---|---|---|
1dff5fe4 | 1dff5fe420d49743fe444a04fc17f818eea856699dec2ebbc24df15602c74a58 | ecdsa_p256_sha256 | 2026-08-17 | 現在の署名鍵 |
計画的なローテーションは、新しい鍵が最初のチェックポイントに署名する少なくとも30日前にこのページで告知されます。その告知期間中、新しい鍵は切り替え日とともにlog_keysおよびこの表に記載されます。廃止済みの鍵は、その使用期間とともにリストに残ります。この表に記載されていない鍵は、GET /keysが何を返しても正当なものではありません。記載されたどの鍵でも検証できないチェックポイントは検証失敗として扱い、Anthropicのアカウント担当者またはAnthropicサポートに報告してください。
axt-verifyは各リリースに現在の鍵を含んでおり、APIから鍵を読み取ることはありません。各リリースにはちょうど1つの鍵が含まれます。切り替え日に、Anthropicは新しい鍵での署名を開始し、その鍵を含むaxt-verifyリリースを公開します。同じ日に、Anthropicは、拡大していないログであっても、すべての組織の最新のチェックポイントを新しい鍵で再発行します。切り替え日にアップグレードしてください。切り替え後に古いリリースを実行すると終了ステータス1で失敗し、切り替え前に新しいリリースを実行した場合も同様です。どちらの失敗も、対応するリリースを実行すれば解消されます。自分で保守している検証者の場合は、その日付より前に、新しいフィンガープリントを切り替え日とともに追加する必要があります。
包含証明を取得する
GET /v1/compliance/transparency_log/inclusion?leaf_index={index}
| パラメータ | 型 | 説明 |
|---|---|---|
leaf_index | integer、必須 | ログ内でのイベントの位置:Activity Feedがイベントで提供したtransparency_log_leaf_index。0以上である必要があります |
organization_id | string、省略可能 | 認証とスコープを参照してください |
curl --fail-with-body -sS -G \
"https://api.anthropic.com/v1/compliance/transparency_log/inclusion" \
--data-urlencode "leaf_index=41" \
--header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
--header "anthropic-version: 2023-06-01"{
"type": "transparency_log_inclusion_proof",
"leaf_index": 41,
"hashes": [
"mUdyOWMp0zXIq0CDMvSYDUSBl9yAvnTZzdm51RwWpUM=",
"yR6tDHkAhKvdQSLqQATVjXOo4GM3FDyiKF2XCKTtMUI=",
"..."
],
"checkpoint": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b\n42\nCsRlS31ITFHrX9GR5XjyPw8n0MkfrB8Yh2UDHl3Lr3E=\n\n— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBEAiB0…(base64)…\n"
}| フィールド | 型 | 説明 |
|---|---|---|
type | string | 常にtransparency_log_inclusion_proof |
leaf_index | integer | ログ内でのイベントの位置。リクエストからそのまま返されます |
hashes | array of strings | 監査パスのbase64の兄弟ハッシュ。リーフからルートに向かう順に並んでいます |
checkpoint | string | 最新の署名付きチェックポイントで、証明の検証対象となるもの。ツリーサイズを含みます |
アクティビティIDによる検索はありません。インデックスはイベントとともに届くため常に保持しており、証明はフィードから取得したイベントのバイトに対して確認します。
404は、最新の公開済みチェックポイントが指定された位置をカバーしていないことを意味します。
- 提供されたイベントから読み取ったインデックスの場合、これは一時的なものです。カバーするチェックポイントはまもなく公開されるため、少し待ってから再試行してください。
- 同じ
404は、フィードが一度も提供していないインデックスなど、カバーされていない他の位置にも返されます。そのような位置については、カバーするチェックポイントが公開されるという保証はありません。レスポンスはどちらのケースであるかを示しません。
leaf_indexが欠落しているか、非負の整数でない場合は400が返されます。
一貫性証明を取得する
GET /v1/compliance/transparency_log/consistency?from={size}
| パラメータ | 型 | 説明 |
|---|---|---|
from | integer、必須 | 保持している以前のチェックポイントのツリーサイズ。1以上かつ最新のチェックポイントのツリーサイズ以下である必要があります |
organization_id | string、省略可能 | 認証とスコープを参照してください |
curl --fail-with-body -sS -G \
"https://api.anthropic.com/v1/compliance/transparency_log/consistency" \
--data-urlencode "from=1180" \
--header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
--header "anthropic-version: 2023-06-01"{
"type": "transparency_log_consistency_proof",
"hashes": [
"dGw0aPzu2N0pdc4C5ZAvNIbkXF7J6F9ZQLkPpV6v8Vg=",
"9PSWm1T9RUmhjF6z6YQzB9CW6E2m2n3mK0aVgqf5Qm0=",
"..."
],
"checkpoint": "axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b\n1207\nC6C4HzGRqDNlbu54LWCvpDX0NcB5DRTmLcjM4u5vWUI=\n\n— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBFAiEAvL8m…(base64)…\n"
}| フィールド | 型 | 説明 |
|---|---|---|
type | string | 常にtransparency_log_consistency_proof |
hashes | array of strings | base64の証明ハッシュ。RFC 9162の順序です |
checkpoint | string | 最新の署名付きチェックポイントで、証明の拡張先となるもの。ツリーサイズを含みます |
- 証明は常に最新の公開済みチェックポイントまで拡張されます。このAPIは過去のチェックポイントを提供しません。提供されたチェックポイントは自分で保持してください。
fromが最新のチェックポイントのツリーサイズと等しい場合は、空の証明が返されます。- ツリーサイズ0の保持チェックポイントには一貫性証明は不要です。すべてのログは空のログを拡張するためです。その場合は最新のチェックポイントを直接採用してください。
fromが1未満、または最新のチェックポイントのツリーサイズより大きい場合は400が返されます。- ログが、かつて組織向けに署名したチェックポイントを拡張していることを証明できなくなった場合は、使用上のエラーではなく検証失敗として扱ってください。
ハッシュタイルを読み取る
GET /v1/compliance/transparency_log/tile/{level}/{index}
tlog-tilesに従い、連結された32バイトのSHA-256ハッシュであるapplication/octet-streamを返します。タイルのアドレス指定は、{level}と{index}のパス文法、大きなツリー向けのx001/234インデックス形式、部分タイルのサフィックス.p/{width}を含め、tlog-tilesに厳密に従います。ハッシュタイルは、tlog-tilesクライアントが自分で証明を計算するための単位です。
- 完全なタイルは不変であり、
Cache-Control: private, max-age=604800, immutableで提供されます。 - 部分タイルはツリーの拡大に伴って置き換えられ、
Cache-Control: private, no-storeで提供されます。タイルが満たされると、完全なタイルが存在していても、以前の部分形式へのリクエストが404を返す場合があります。tlog-tilesが規定しているとおり、部分タイルから完全なタイルへのフォールバックはクライアントの役割であり、標準的なクライアントはすでにこれを行っています。 level、index、または部分タイルの幅の形式が不正な場合は400が返されます。現在のツリーサイズを超えるタイル位置は404を返します。
エントリバンドルを読み取る
GET /v1/compliance/transparency_log/tile/entries/{index}
tlog-tilesに従い、それぞれにビッグエンディアンのuint16長がプレフィックスとして付いた連続するリーフエントリであるapplication/octet-streamを返します。エントリバンドルにはイベントの平文、つまり各Access Transparencyイベントの正規バイトが含まれます。そのため、サーフェス全体でActivity Feedのスコープが必要になります。アドレス指定、部分形式、キャッシング、エラーはハッシュタイルと同じです。
Activity Feedイベントのtransparency_log_leaf_indexフィールド
GET /v1/compliance/activities上のanthropic_accessおよびcmek_preserveイベントには、イベントにリーフがある場合は常に整数のtransparency_log_leaf_indexが含まれます。他のアクティビティタイプには含まれません。
- イベントにリーフがない場合、キーは
nullではなく存在しません。 堅牢な検証者は、キーが存在しない場合とnull値を同じように扱います。 - イベントが
transparency_log_leaf_indexなしで提供されるのは2つのケースのみです。 1つ目は、組織がAccess Transparencyに登録されていない間、つまり登録前、または登録解除から再登録までの間です。2つ目は、組織のログが作成される前にイベントが記録された場合です。透明性ログの導入前に登録された組織の場合、これにはそれ以前の履歴が含まれます。ログが存在し、登録されている間は、すべてのイベントがフィードで提供される前にログに追記されます。障害によってフィードがインデックスを取得できない場合、フィードはインデックスなしでイベントを提供するのではなく、イベントを遅延させます。イベントは失われません。すでにログに含まれており、障害が修復されるとインデックスを含めてフィードに表示されます。ログの作成後の日付で、登録されていた期間内にあるイベントにインデックスがないことは想定されていません。 - 存在するインデックスはポインタであり、証明ではありません。 イベントをログにコミット済みとして扱う前に、包含を検証してください。エスカレーションすべき異常は、カバーするチェックポイントが公開されているはずの時期を大幅に過ぎても、包含証明を取得できないインデックスが存在する場合です。
- インデックスはイベントがログに追記されたときに割り当てられ、リーフを構成するフィールドの1つではありません。
イベントがリーフになる仕組み
リーフエントリは、スキーマバージョンバイト0x01の後に11個のフィールドの正規JSONが続くものです。JSONはRFC 8785(JSON Canonicalization Scheme)に従い、フィールドはActivity Feedが提供するとおりのイベントから取得されます。
id、type、created_at、accessed_at、organization_id、organization_uuid、workspace_id、accessor_department、reason_code- ネストされた
typeとemail_addressを持つactor - ネストされた
type、id、parentを持つresource_details
ルール:
workspace_uuidやtransparency_log_leaf_index自体など、そのセット外で提供されるフィールドは無視されます。- 提供されたイベントで省略されているドキュメント化されたフィールドは、
nullとしてリーフに入ります。空文字列はnullとは区別されます。 actorとresource_detailsは、提供されたイベントに含まれている場合、ドキュメント化されたキーをちょうど持つオブジェクトです。バージョン0x01では、actor.email_addressとresource_details.parentは常にnullです。提供されたイベントがこれらのオブジェクトのいずれかを省略しているかnullとして提供している場合、リーフ内の値全体がnullになり、nullフィールドのオブジェクトにはなりません。多くのアクセスイベントにはresource_detailsが含まれません。- 両方のタイムスタンプと
reason_codeを含む文字列値は、提供されたとおりにバイト単位で取得されます。別の表現からタイムスタンプを再導出する場合は、提供された表記を正確に再現してください。Zサフィックス付きのRFC 3339 UTC。created_atは、マイクロ秒がゼロの場合は小数桁がなく、それ以外の場合はちょうど6桁です。accessed_atは、ナノ秒を正確に保持する最短の桁数として、0、3、6、または9桁の小数桁を持ちます。
- 正規JSONとは、オブジェクトのキーがソートされ、意味のない空白がなく、文字列のエスケープが最小限であることを意味します。リーフのどこにも数値は現れません。
- リーフハッシュはRFC 6962の
SHA-256(0x00 || entry)です。内部ノードはSHA-256(0x01 || left || right)としてハッシュされます。 - 検証者は、不明なバージョンバイト、および
typeが2つのAccess Transparencyタイプのいずれでもない0x01リーフを拒否します。新しいイベントタイプやルールの変更は、新しいバージョンバイトで提供されます。既存のリーフが再ハッシュされることはありません。
たとえば、Activity Feedが提供するこのアクセスイベントは、
{
"id": "activity_01GPXmAhizavrUuoXNn3tzeA",
"type": "anthropic_access",
"created_at": "2025-07-08T18:40:00Z",
"accessed_at": "2025-07-08T18:39:58Z",
"organization_id": "org_015gtSHLz269eTwgrH8NX5yk",
"organization_uuid": "25f6429a-3293-49bf-afed-cb312911554b",
"workspace_id": "wrkspc_01PaGUP2rbg1XDh7Z9W1CEpd",
"workspace_uuid": "b6ce2143-1083-d4a7-247c-17530f55a076",
"accessor_department": "Trust & Safety",
"reason_code": "safety_review",
"actor": { "type": "anthropic_actor", "email_address": null },
"resource_details": { "type": "message", "id": "msg_01HXAMPLE12345678" },
"transparency_log_leaf_index": 17
}次の正規JSONになります。ドキュメント化された11個のキーがちょうど含まれ、ソートされ、1行になっています。workspace_uuidとtransparency_log_leaf_indexは除外され、提供されたイベントに存在しないresource_details.parentはnullとして入ります。
{"accessed_at":"2025-07-08T18:39:58Z","accessor_department":"Trust & Safety","actor":{"email_address":null,"type":"anthropic_actor"},"created_at":"2025-07-08T18:40:00Z","id":"activity_01GPXmAhizavrUuoXNn3tzeA","organization_id":"org_015gtSHLz269eTwgrH8NX5yk","organization_uuid":"25f6429a-3293-49bf-afed-cb312911554b","reason_code":"safety_review","resource_details":{"id":"msg_01HXAMPLE12345678","parent":null,"type":"message"},"type":"anthropic_access","workspace_id":"wrkspc_01PaGUP2rbg1XDh7Z9W1CEpd"}リーフエントリは、バイト0x01の後にそれらのUTF-8バイトが続くものです。そのリーフハッシュSHA-256(0x00 || entry)は、base64で6ro7vTcFq+sYDZiiGvZaFetUIoMSLig3DGDrCKK1HFU=です。この例を、独自の正規化コードのテストベクトルとして使用してください。
ログを検証する
検証はお客様自身のインフラストラクチャで実行します。APIが返すものはすべて、自分で保持している2つのものに対して検証されるまで信頼できません。1つ目は、組織UUIDから導出したオリジンです。2つ目は、前回の実行で保存したチェックポイントです。完全な検証の実行では、以下を順番に行います。
- 検証鍵セットを取得します。各鍵のフィンガープリントを、base64デコードした
public_keyのSHA-256として自分で計算します。フィンガープリントが公開されている鍵フィンガープリントに記載されている鍵のみを、そこでの各鍵のステータスとともに保持します。新しく取得したチェックポイントは、その日付時点でその表に現在の鍵として記載されている鍵でのみ検証してください。廃止済みの鍵は、その廃止日より前に保存したチェックポイントに対してのみ受け入れてください。 - 最新のチェックポイントを確定します。初回の実行では、チェックポイントエンドポイントから取得します。以降の実行では毎回、保存したツリーサイズからの一貫性証明をリクエストします。レスポンスには、証明とともに最新のチェックポイントが含まれます。
- まずチェックポイントのオリジン行を確認します。その最初の行を、導出したオリジンとバイト単位で比較します。オリジンが異なるチェックポイントは、他の何よりも先に拒否してください。
- チェックポイントの署名を検証します。オリジンの名前が付いた署名行のうち、デコードした最初の4バイトが、保持している現在有効な鍵の
key_hashと等しいものを見つけます。残りのバイトを、その鍵のpublic_keyを使用して、ノート本文のSHA-256に対するECDSA P-256署名として検証します。そのような鍵に一致する署名行がない場合、または署名が検証できない場合は、チェックポイントを拒否してください。 - 追記専用であることを証明します。新しいツリーサイズが保存したものより小さい場合は失敗です。等しい場合は、ルートハッシュが一致する必要があります。大きい場合は、保存したサイズとルートハッシュから新しいサイズとルートハッシュへのRFC 9162一貫性証明を検証します。
- 各イベントが含まれていることを証明します。Activity Feedが提供するすべてのAccess Transparencyイベントを読み取ります。新しいイベントごとに、そのリーフを再構築してハッシュし、その包含証明を取得します。イベントのインデックスにあるリーフハッシュから、チェックポイントのルートハッシュまで監査パスをたどります。不一致は、提供されたイベントがログにコミットされたイベントではないことを意味します。証明レスポンスには、保持しているものとは異なるチェックポイントが含まれる場合があります。それに対して何かを検証する前に、一貫性証明でそれを履歴にリンクしてください。
- 以前に確認したものを再確認します。イベントを再度読み取るときは常に、検証したときと同じインデックスと同じリーフバイトで提供される必要があります。どのイベントも持っていたインデックスを失ってはならず、登録されている間は、インデックスなしで新たに表示されるイベントがあってはなりません。初回の実行でインデックスなしで提供されたイベントは、ログ以前の履歴です。最近のイベントのみを再読み取りする実行では、それらのみが再確認されます。古いイベントを再確認するには、保持しているコピー(ステップ8)を再度検証してください。
- 検証したチェックポイントと、検証した各イベントの記録を保存します。これらは証拠であり、次回の実行の出発点となります。
axt-verifyで検証する
axt-verifyは、このログ用のAnthropicのオープンソース検証ツールです。お客様自身のインフラストラクチャで実行する単一のGoバイナリです。各リリースには、公開されている鍵フィンガープリントのログ署名鍵がちょうど1つ組み込まれているため、どの鍵を信頼すべきかをAPIに問い合わせることはありません。Anthropicが鍵をローテーションする際は、切り替え日に新しい鍵を含むリリースにアップグレードします。axt-verifyは、--orgで渡す組織UUID(始める前にでConsoleから取得したもの)からオリジンを導出します。オリジン行が異なるチェックポイントはすべて拒否します。
Go 1.26以降でインストールしてください。Compliance Access KeyはANTHROPIC_COMPLIANCE_ACCESS_KEY環境変数から読み取り、フラグやファイルから読み取ることはありません。スケジュール実行するのはrunコマンドです。
go install github.com/anthropics/axt-verify/cmd/axt-verify@latest
export ANTHROPIC_COMPLIANCE_ACCESS_KEY="<your Compliance Access Key>"
axt-verify --org 25f6429a-3293-49bf-afed-cb312911554b \
--state /var/lib/axt-verify/25f6429a-3293-49bf-afed-cb312911554b.state \
run各runは、最新のチェックポイントを取得し、その署名とオリジン行を検証します。次に、ログが前回の実行で保存したチェックポイントの追記専用の拡張であることを証明します。続いて、Activity Feed上のAccess Transparencyイベントをページングします。遅れて、または順不同で一覧表示されたイベントも取得できるように、前回の実行で読み取った最新のイベントの7日前(created_at基準)から開始します。各イベントのリーフを再構築し、その包含証明を検証し、以前に検証したイベントをそのとき記録した内容と比較します。最後に、新しいチェックポイントと進捗を--stateファイルに保存し、次回の実行はそこから開始します。少なくとも毎日実行してください。1時間ごとが妥当です。親組織のキーを使用する場合は、子組織ごとに1つのコピーを、それぞれ独自の--orgと--stateファイルで実行してください。各子組織のUUIDも、検証対象のCompliance APIレスポンスからではなく、Claude Consoleから取得します。子組織のSettings > Organizationページ、またはConsoleの親組織の組織一覧で確認できます。axt-verify checkpointは、チェックポイントと追記専用のステップのみを実行します。axt-verify events FILEは、監査人のサンプルや独自のエクスポートなど、すでに保持しているイベントを検証します。ファイル内の各イベントが、現在のチェックポイントの下でログに依然としてコミットされていることを証明します。フィードの読み取りや状態ファイルへのアクセスは行いません。
このウィンドウから1つの制限が生じます。runは直近7日間のイベントのみを再読み取りするため、履歴全体ではなく、最近提供されたイベントのみを再確認します(ステップ7)。エクスポートしたイベントは保持してください(独自のチェックポイントアーカイブを保持するを参照してください)。axt-verify events FILEは、後日いつでもそれらのコピーがログに依然としてコミットされていることを証明しますが、フィードを再読み取りすることはありません。フィードから削除された、またはフィード上で書き換えられた古いイベントを検出するには、その範囲をActivity Feedから再エクスポートし、保持しているコピーと比較してください。再エクスポート自体をaxt-verify events FILEで検証することもできます。7日間の重複期間はフィードの2営業日の配信時間より長いため、遅れて届いたイベントも後の実行のウィンドウ内に収まります。必要に応じて、--overlapで期間を変更できます。
代わりに独自の実装が必要な場合は、ECDSAノート鍵をサポートするtlog-tilesライブラリを使用して、前述のチェックリストに従ってください。
結果を解釈する
axt-verifyは、オリジン、検証したチェックポイントのツリーサイズとルートハッシュ、追記専用チェックの開始点となったツリーサイズ、および結果別のイベント数を出力します。--jsonを渡すと、同じレポートを1行につき1つのJSONオブジェクトとして取得できます。各イベントの結果は次の4つのいずれかです。
- Verified(検証済み): 提供されたイベントから再構築されたリーフが、署名済みログ内のイベントのインデックスにコミットされています。
- Pending(保留中): イベントのインデックスが、最新の公開済みチェックポイントの範囲を超えています。これはイベントが表示された直後の短い間は正常な状態です。
runでは、axt-verifyはそのイベントを記憶し、チェックポイントがそれをカバーした後の実行で検証します。24時間を超えた場合は失敗とします。events FILEには決着をつける後続の実行がないため、カバーするチェックポイントが公開されるまで最大1分間待機します。何も届かない場合は、そのイベントをまだカバーされていないと報告し、終了ステータス3で終了します。後でもう一度実行してください。少なくとも1日の間隔を空けた2回の実行で、events FILEが同じイベントをまだカバーされていないと報告した場合は、検証失敗として扱い、終了ステータス1と同様にエスカレーションしてください。 - Not logged(未記録): イベントがインデックスなしで提供されました。イベントが
transparency_log_leaf_indexなしで提供されるのは、組織がAccess Transparencyに登録されていない間、またはイベントが組織のログ作成前に記録された場合のみです(Activity Feedイベントのtransparency_log_leaf_indexフィールドを参照)。axt-verifyはそのようなイベントを未記録として報告し、それを理由に実行を失敗させることはありません。ログ作成後の日付で、かつ登録期間内に該当するイベントにインデックスがないことは想定されていません。終了ステータスだけに頼るのではなく、実行のサマリーまたは--json出力にある未記録リストを確認してください。 - Failed(失敗): 終了ステータス
1を参照してください。
終了ステータスは、スケジューラーに何が起きたかを伝えます。
-
0: 何も失敗しませんでした。未記録のイベントは報告されますが失敗にはならず、runにおける保留中のイベントも同様です。 -
1: 検証失敗です。これは一時的なエラーではなく、セキュリティ上の発見事項です。状態ファイルと出力を保持し、Anthropicのアカウント担当者またはAnthropicサポートに報告してください。原因は次のとおりです。- オリジンが誤っているチェックポイント、または使用している
axt-verifyリリースに組み込まれた鍵で検証できない署名。失敗したチェックポイントの署名行にあるkey_hashを公開されている鍵フィンガープリントと比較してください。そこに記載されている鍵で、まだアップグレードしていない切り替え日が付いているものであれば、対応するリリースが必要です。そこに記載されていない鍵は、どのリリースを実行しているかにかかわらず、セキュリティ上の発見事項です。この失敗時、axt-verifyは提供されたチェックポイント上のすべての署名の鍵ハッシュと、信頼している鍵の鍵ハッシュを、それぞれ8桁の16進数で出力します。この出力だけで比較を行うことができます。 - 正しい形式の署名付きノートではないチェックポイント。たとえば、ルートハッシュが32バイトではないものなど。
- 縮小したログ、または保存したチェックポイントを拡張していることを証明できないログ。この場合、出力には両方のチェックポイントと証明が含まれるため、証拠はそれ単体で成立します。
- 同じツリーサイズに対して、ルートハッシュが異なる2つの署名済みチェックポイント。出力には両方のチェックポイントが含まれます。
--fromで渡されたチェックポイントファイルの署名が、使用しているaxt-verifyリリースに組み込まれた鍵で検証できない場合、または--fromや--from-trustedのファイルのオリジンが自分のものではない場合。鍵のローテーション前に署名されたアーカイブについては、独自のチェックポイントアーカイブを保持するを参照してください。- 提供されたイベントについて、署名済みルートハッシュを再現しない包含証明。
- 実行のウィンドウ内のイベントが、以前の実行で記録された内容と異なって提供された場合:リーフのバイトが異なる、インデックスが異なる、またはインデックスがあったのにない場合。
- 実行が最初に検出してから24時間経っても保留中のままのイベント。
- フィードが提供したイベントに対する包含証明が拒否された場合(
400、401、または403)。 - 要求したものとは異なる
leaf_indexに対して返された包含証明。 events FILEにおいて、チェック開始時点で最新のチェックポイントがすでにカバーしていたインデックスにあるイベントで、待機時間が切れるまでに包含証明が提供されなかったもの。organization_uuidが--orgで渡した組織UUIDと一致しないイベント。親組織が複数の子組織をカバーするエクスポートに対してevents FILEを実行すると、他のすべての組織のイベントがこの理由で失敗します。そのため、まずエクスポートを組織ごとに分割し、各部分をそれぞれの--orgで検証してください。- 1回の実行または1つの
events FILE入力内で、同じアクティビティidが2つの異なるインデックスにある場合、または1つのインデックスに異なる内容で2回ある場合。 - リーフを再構築できないイベント:たとえば、ドキュメント化されたフィールドが文字列ではない、フィールド名が2回出現する、または
typeが欠落しているかAccess Transparencyタイプの認識されないバリアントである場合など。events FILEは他のアクティビティタイプの行をスキップし、それらを失敗にはしません。
- オリジンが誤っているチェックポイント、または使用している
-
2: 使用方法または設定のエラーです。原因は次のとおりです。- フラグの欠落または不正な形式。
ANTHROPIC_COMPLIANCE_ACCESS_KEYがない。- いずれかのチェックポイントが検証される前に、APIが鍵を拒否した(
401または403)。 - 読み取れない状態ファイル、または別のオリジンに属する状態ファイル。
-
3: 実行を完了できませんでした。runでは、すでに検証された内容は状態ファイルに保存されます。もう一度実行してください。原因は次のとおりです。events FILE内のイベントで、待機時間内にそのインデックスをカバーする公開済みチェックポイントがなかったもの。そのようなイベントについては、Pending の結果の説明に、再実行をやめてエスカレーションすべきタイミングが記載されています。- 再試行の回数を超えて続いたネットワークエラー、レート制限、またはサーバーエラー。
- 予期しないレスポンス。
- 書き込めなかった状態ファイルまたは
--saveファイル。
Anthropicが組織の最初のAccess Transparencyイベントを記録するまでは、
404レスポンスを伴う終了ステータス3は想定どおりです。そのイベントがログを作成するまで、すべての透明性ログエンドポイントが404を返すためです。Activity Feedに最初のAccess Transparencyイベントが表示されてから数日以上経っても透明性ログエンドポイントが404を返し続ける場合は、そのイベントにtransparency_log_leaf_indexが含まれているかどうかにかかわらず、エスカレーションしてください。その組み合わせは想定されていません。一度実行が成功した後は、継続する終了ステータス3をエスカレーションしてください。
独自のチェックポイントアーカイブを保持する
保持できる最も強力な証拠は、特定の日にログが示していた内容についての独自の記録です。axt-verify --save FILEは実行で検証したチェックポイントをそのまま書き出し、後の実行で--from FILEを使用すると、ログがそのチェックポイントを引き続き拡張していることを証明させることができます。保存したチェックポイントを、たとえば毎日、自分が管理するストレージにアーカイブしてください。数か月後でも、アーカイブしたチェックポイントのツリーサイズからの一貫性証明は、ログが提供するチェックポイントへと必ずつながらなければならず、そうでなければ検証は失敗します。計画的なローテーションの後も、以前の鍵は検証鍵セットに記載されたままなので、アーカイブしたチェックポイントは引き続き検証できます。axt-verifyでは、アーカイブしたチェックポイントに署名した鍵がその後ローテーションで外れた場合、そのアーカイブを--fromではなく--from-trustedで渡してください。イベントも保持してください。フィードからエクスポートしたAccess Transparencyイベントはaxt-verify events FILEの有効な入力であり、後日いつでも、それらのコピーが現在のチェックポイントのもとでログに引き続きコミットされていることを証明します。events FILEはフィードを再読み込みしないため、保持しているエクスポートは、同じ範囲を後で再エクスポートしたものと比較する際の基準にもなります。
よくある質問
いいえ。Anthropicは、誰かが検証するかどうかにかかわらず、組織のログを維持します。検証は、ログを自分自身で確認するための手段です。監査人は、Activity FeedスコープのAPIキーがあれば、同じ手順で、あなたが渡したイベントのサンプルを検証できます。
そのイベントは、その位置をカバーするチェックポイントが公開される直前に提供されました。カバーするチェックポイントはまもなく公開されるため、少し時間を置いてから再試行してください。1日経っても証明が利用できないイベントは、エスカレーションすべき異常です。
計画的なローテーションは、少なくとも30日前に切り替え日とともに公開されている鍵フィンガープリントで告知されます。切り替え日に、Anthropicは新しい鍵での署名を開始し、その鍵を含むaxt-verifyリリースを公開します。同じ日に、Anthropicはログが増えていない場合でも、すべての組織の最新チェックポイントを新しい鍵で再発行します。各axt-verifyリリースには1つの鍵が含まれているため、切り替え日にアップグレードしてください。切り替え後に古いリリースを実行すると終了ステータス1で失敗し、切り替え前に新しいリリースを実行した場合も同様です。どちらの失敗も、対応するリリースを実行すれば解消されます。古い鍵で保存したチェックポイントは引き続き有効な開始点です。保存したチェックポイントから新しいチェックポイントへの追記専用の証明は、古いチェックポイントにどの鍵が署名したかに依存しないためです。新しい鍵は検証鍵セットの先頭に表示され、以前の鍵も記載されたままです。そのため、すでに検証またはアーカイブしたチェックポイントは、そのセットに対して引き続き検証できます。公開されたフィンガープリントを固定している独自の検証者では、切り替え日より前に、新しいフィンガープリントをその切り替え日とともに追加する必要があります。鍵セットをローカルに保持している検証者は、保持していない鍵ハッシュの署名に遭遇すると、鍵セットを再取得します。チェックポイントは履歴全体にコミットします。新しい鍵で署名されたチェックポイントが1つ検証され、保存したチェックポイントからの一貫性証明がそれにつながれば、それ以前のすべてのエントリも再確立されます。
はい。ハッシュタイルが主要なインターフェースであり、ECDSAノート鍵をサポートするtlog-tilesクライアントは、それらから包含証明と一貫性証明を計算できます。証明エンドポイントは利便性のためのものです。汎用クライアントでは、x-api-keyヘッダーと、親組織の鍵の場合はorganization_idパラメータを送信するための薄いラッパーが必要です。
何も削除されません。ログは同じエンドポイントを通じて引き続き読み取りおよび検証が可能なので、これまでどおり検証を続けてください。後で組織が再びAccess Transparencyを有効にした場合、同じログが継続され、一貫性証明はその空白期間をまたいで機能します。
はい。親組織の鍵は、organization_idを渡すことで、登録済みの任意の子組織のログを読み取れます。各子組織には独自のログ、オリジン、保存済みチェックポイントがあります。子組織ごとに、それぞれ独自の状態で1回ずつ検証を実行してください。
関連リソース
- Access Transparency
- アクティビティフィードをクエリする
- Compliance APIの概要
- エラー
- axt-verify:透明性ログ用のAnthropicのオープンソース検証ツール
- C2SP tlog-tiles および C2SP signed note:タイル、エントリバンドル、チェックポイントのワイヤ形式
- RFC 9162:Merkleツリー、包含証明、一貫性証明のアルゴリズム
- RFC 8785:リーフに使用されるJSON Canonicalization Scheme
Was this page helpful?