変更履歴¶
英語版の参考訳です(02/11/2026 更新)。各エントリーは、
[Unreleased]のものも含め、その時点での変更を記述したもので、現在の動作を保証するものではありません。公開済みの各バージョンは日付のある過去の記録です。内容が異なる場合は英語版が優先されます。
公開済みバージョン(2026 年 10 月 26 日)。 npm(@dcp-ai/sdk 2.2.0 を含む 13 パッケージ)、Python dcp-ai 2.10.0、Go v2.11.0、Rust dcp-ai 2.11.0 が、検証器の修正、受け入れ判定、実験的なオプトイン API を含めて公開済みです。dcp-jcs-v1 は引き続き規範的なデフォルトです。公開済みバージョンを参照してください。以下の項目は開発履歴として保持しています。[Unreleased] はこれらの機能が未公開であることを意味しません。2026 年 10 月 28 日の 6 つの修正リリースは専用のセクションにあります。
このプロジェクトの重要な変更はすべてこのファイルに記録します。
形式は Keep a Changelog に基づいています。
参考の注記(2026 年 10 月 25 日)。 各エントリーは、
[Unreleased]の後続のエントリーも含め、変更をそれが行われた 時点のとおりに記述しています。そこでは、後のエントリーが前のエントリーを補足したり置き換えたりすることが あります。エントリーは現在の動作も、パッケージのバージョンがレジストリで入手できることも保証しません。現在の動作に ついては、README、ドキュメント、仕様、 API リファレンスを参照してください。
準備済み・未公開: Go v2.12.0、Rust 2.12.0、@dcp-ai/wasm 2.1.2¶
30/10/2026 にリポジトリで準備済みで、公開されていません。sdks/go/v2.12.0 タグは存在せず、crates.io と npm にもこれらのバージョンはありません。公開済みバージョンとインストールコマンドは、引き続きレジストリのバージョン(Go v2.11.1、Rust dcp-ai 2.11.1、@dcp-ai/wasm 2.1.1)を示します。変更内容は [Unreleased] と、Go、Rust、npm のリリースノートに記載されています。
- Go v2.12.0:
v2.VerifyPayloadHashの受け入れの変更(SignPayloadの出力を受け入れ、接頭辞のないダイジェストを拒否する。確認するのはハッシュだけ)と、追加されたv2.RawAuditEventV2。SDKVersionは2.12.0です。 - Rust
dcp-ai2.12.0: 追加されたv2::types::RawAuditEventV2とRawAuditEventError、およびwasmフィーチャー使用時の修正済みwasm_dual_merkle_root。テレメトリーはパッケージのバージョンを読み取ります。 @dcp-ai/wasm2.1.2:dualMerkleRootとwasm_dual_merkle_rootが V2-11 の二重マークルルートを計算します。JavaScript API の追加はありません。- 実験的候補の新しいテスト(ゲート 7)はどのデフォルトも変更しません。
dcp-jcs-v1、プロファイル、ワイヤーフォーマット、依存関係、暗号は変わりません。3 つのパッケージには翻訳版 README が含まれなくなりました。これらはi18n/にあります。
[2026-10-28] SHA3 の修正リリース¶
2026 年 10 月 28 日に公開:npm の @dcp-ai/sdk 2.2.1、@dcp-ai/wasm 2.1.1、@dcp-ai/cli 2.1.1、PyPI の dcp-ai 2.10.1、Go モジュール v2.11.1(タグ sdks/go/v2.11.1)、crates.io の Rust dcp-ai 2.11.1。その他の 10 の npm パッケージは変わりません。公開済みバージョンと、npm、Python、Go、Rust のリリースノートを参照してください。
二次 SHA3-256 の検証¶
- 受け入れの変更:二次の SHA3-256 フィールドは、存在する場合に検証されます(2026 年 10 月 27 日に開発)。
TypeScript、Python、Go、Rust の V2 検証器と、Rust SDK からの WASM ビルドは、
spec/VERIFICATION.mdの V2-11 と 2026 年 10 月 27 日の正誤のとおり、audit_merkle_root_secondary(一次と同じ方法で作る SHA3-256 の木。空の記録ではsha3-256:に 64 個のゼロを続けた値)、各prev_hash_secondary(最初のエントリーでは"GENESIS"、以降はバンドルに 含まれているとおりの直前のエントリーの SHA3-256)、各intent_hash_secondary(インテントのペイロードの SHA3-256)を 確認するようになりました。存在しないフィールドは要求されないため、検証済みのバンドルが完全な二次チェーンを持たない こともあります。存在するフィールドがnull、文字列でない、または誤っている場合は拒否されます。受け入れと実験的な 候補の経路もこれらの確認を再利用します。API、結果のフィールド、正規化、hash_algの扱いは変わりません。prev_hash_secondaryのスキーマのパターンは、OpenClaw が最初のエントリーに書く"GENESIS"も受け入れます。共有 ベクター:tests/interop/v2/secondary_sha3_vectors.json。以前のバージョンはこれらのフィールドを確認しません。 公開済みのアダプター@dcp-ai/express、@dcp-ai/openclaw、@dcp-ai/anthropic-mcp、@dcp-ai/google-a2a2.1.0 は再公開していません。これらは@dcp-ai/sdk^2.2.0に依存しており、ロックファイルが@dcp-ai/sdk2.2.1 以降を解決すると二次の確認が行われます。
パッケージのメタデータ¶
@dcp-ai/cli2.1.1 は@dcp-ai/sdk^2.2.1を必要とし、dcp-ai --versionは古い1.0.0ではなく2.1.1を表示します。- テレメトリーは新しいバージョンを報告します:Go の
SDKVersionは2.11.1。TypeScript、Python、Rust の SDK は自身のパッケージのバージョンを読み取ります。
[Unreleased]¶
セキュリティ¶
- 受理の変更:各 SDK の検証器での V2-2 スキーマ検証(
mainのソースコード、公開済みのどのバージョンにも含まれない)。 TypeScript、Python、Go、Rust、WASM の各 SDK の V2 検証器(verifySignedBundleV2とその対応関数、最初に検証を行う結合された アドミッション API、実験的な候補の検証器。以前の結果からアドミッションを評価する場合は実行されない)は、ポリシーと時計の 確認の後、マニフェスト、ペイロードのハッシュ、鍵、署名を確認する前に、署名済み bundle のエンベロープと四つのペイロードをschemas/v2に照らして検証します。すべての SDK はスキーマから生成された同じ表現(tools/schema-ir/)を解釈し、CI はそれを 再生成して比較します。以前は受け入れていたスキーマ上無効な bundle は、今はverified: falseを返します。閉じたオブジェクトの 未知のメンバーや、マニフェストのnullのセッション時刻がその例です。そのときのエラーは暗号に関する詳細のないschema: <JSON pointer> <keyword>[ <member>]の診断(最大 16 件と切り捨ての印)なので、一部の拒否は文言が変わります。CI は 証拠カタログの SDK 実行を判定で評価し(--assessment verdict)、コミット済みのerror_containsの文字列は変わりません。date-timeは参照検証器の ajv-formats 3.0.1 の境界を保ち、これは厳密な RFC 3339 ではありません。公開 API、スキーマ、 プロファイル、依存関係、バージョンは変わりません。実験的なフェーズ 4 のマトリクスでは、S09の 50 の結果が想定どおりの 拒否になりました。SECURITY_COVERAGE.md を参照してください。 - TypeScript の
VerificationCache(mainのソースコード、未公開。@dcp-ai/sdk2.2.1 は以前の動作のまま)。 既存の呼び出しではキャッシュのキーは引き続きバンドルのハッシュで、呼び出し側が選ぶオプトインのcontextは、レガシーのハッシュと衝突しないタグ付きの内部キーで結果を分けます。 何も削除しなかったinvalidateByAgentは、新しいagentIdsオプションでそのエージェントを付けて保存したエントリと、それなしで保存したすべてのエントリを削除するようになりました。 エントリを置き換えても、古い kid が索引に残ること(既定の上限では索引が際限なく増えていました)や、別のエントリを追い出すことはなくなりました。result.details.signer_keysの kid も索引付けされます。 ハッシュ''がmaxEntriesを無効にすることもなくなりました。 受け入れの変更: 不正なオプション(NaN、Infinity、負または数値でない TTL、Number.MAX_SAFE_INTEGERを超える TTL、1 からNumber.MAX_SAFE_INTEGERまでの安全な整数でないmaxEntries)は、期限や上限を無効にする代わりにエラーを投げます。setは結果をコピーし、getはヒットのたびに新しいコピーを返します。 エントリは TTL ちょうどで期限切れになり、壁時計に加えて単調時計でも測るため、時計の巻き戻しで延びることはなくなりました。 TTL が 0 のエントリは保存されません。setは引数を検証し(signerKidsやagentIdsの穴はundefinedとして扱います)、エラーを投げたときは何も変えません。 ヒットは引き続き証拠や信頼を再検証せず、アドミッションではありません。自動的に無効化されるものもありません。 API_REFERENCE.md を参照してください。 - 受け入れの変更: S >= L の Ed25519 署名を拒否するようになりました。 対象は TypeScript SDK
(
Ed25519Provider.verify、したがってすべての V2 署名と複合署名、@dcp-ai/expressと@dcp-ai/openclaw。さらにverifyObject、したがってverifySignedBundleV1)と、リファレンスの検証者 (tools/crypto.js、したがってlib/verify.jsV1、bin/dcp.js、適合性テスト、透明性ログの ゴシップ)です。RFC 8032 §5.1.7 は 0 <= S < L を求めていますが、TweetNaCl はこれを確認しないため、 有効な署名の別のエンコーディングである S + k·L を受け入れていました(§8.4、展性)。Python、Go、Rust は すでに拒否していました。検証者は引き続き TweetNaCl です。範囲は TweetNaCl が受け入れた入力に対してだけ 確認するため、型、サイズ、base64 の誤りに対するエラーは変わらず、鍵と R のデコードや弱い鍵の受け入れも 変わりません。署名者は S < L を生成するため、新たに生成された署名の判定は変わりません。以前のバージョンが 受け入れた S >= L の保存済み署名は、もう検証に成功しません。リポジトリの棚卸しでこうした署名が見つかったのは、 意図的に作った否定的なレビュー用コーパスの中だけでした。外部に保存された証拠は対象外です。この変更より前に 検証された証拠は自動的に再署名されません。ハッシュとそれを検証したバージョンとともに履歴として保管するか、 署名し直してください。 - 同じ受け入れの変更を
dcp-ai verify(@dcp-ai/cli)とプレイグラウンドにも適用しました。 どちらも TweetNaCl を直接呼び出していました。dcp-ai verifyはsignature.sig_b64に対する独自の V1 チェックで S < L を確認し、V2 の bundle については、今は検証者として使っている@dcp-ai/sdkから確認を受け継ぎます (「変更」を参照)。履歴上のsignature.classical.valueの経路も、追加された時点ではこの確認を持っていました。 その経路はその後削除され、その形式は拒否されます。プレイグラウンドはverifyDetachedで確認します。確認は SDK のもので、TweetNaCl が受け入れた入力に対してだけ行うため、エラーは変わりません。 - 4 つの V2 検証者は、有効な署名の正規でないエンコーディングに対して判定が分かれていました。パディングの後の
余計なデータ、余分なパディング、途中の改行、末尾ビットが立っているもの、パディングなしについて、TypeScript は
すべての変種を、Python と Go は一部を受け入れ、Rust はどれも受け入れませんでした。今はすべての
sig_b64が 正規の base64 でなければなりません(spec/VERIFICATION.mdV2-5)。これにより署名のエンコーディングは 1 つに なり、すべての SDK が同じバイト列をデコードします。新しい 13 個のmust_rejectベクターでこれを確認します。 - 4 つの SDK の V2 検証者は、署名だけを見れば通るがプロトコル上は認められない bundle を受け入れていました。
外部レビューで報告され、私たち自身のレビューでも確認しました。リファレンスの検証者
lib/verify.jsは、 2.2.0 が npm に公開されるまで、ワークスペースの SDK を通じて修正済みの検証者を実行します(「変更」を参照)。 - どのエージェントでも任意のプリンシパルを名乗れました。 bundle の署名は RPR の
binding_keysに加えて パスポートの鍵でも検証されており、エージェントは自らのパスポートに署名します。公開済みで署名付きの RPR を 新しいパスポートと鍵と組み合わせると、プリンシパルの秘密鍵なしで検証済みの bundle が得られました。 bundle の署名は今では RPR のbinding_keysでだけ検証されます(spec/VERIFICATION.mdV2-6)。そのため、 エージェントを結び付けるのは、passport_hashにコミットするマニフェストへのプリンシパルの署名です。 - kid が鍵と照合されていませんでした。 鍵のリストは、自分の鍵について他者の kid を名乗ることができました。 今は、署名を検証するすべての kid がその鍵から導出されていなければならず、すべての SDK が同じバイト列を デコードするよう、鍵は正規の base64 でなければなりません(V2-13)。
- 署名はあるが一貫しない bundle が検証に成功していました。 失効または運用終了したパスポート、期限切れの
RPR、別の意図に対するポリシー決定、別の意図、エージェント、プリンシパルの監査エントリー、別の
intent_hashを持つ、またはポリシー決定を記録していない監査エントリーです。V1 のチェックは今では V2-14 に なりました。パスポートはactiveまたはdeclining、RPR は期限切れでなく、すべての成果物が同じ プリンシパル、エージェント、意図を示していることです。エスカレートまたはブロックされた行動も、有効な証拠で あることに変わりはありません。 - セッション継続時間の上限が署名されていないフィールドを読んでいました。
max_session_duration_secondsは、 署名済みマニフェストの外にあるsignature.created_atから測られていました。マニフェストには新しいsession_issued_atがあり、signBundleV2とsign_bundle_v2がsession_expires_atとともに書き込みます。 上限はそこから測られ、上限がある場合、それを持たない bundle は拒否されます(V2-4)。 それが検証者の時計より 30 秒を超えて先行していてはならず、上限がある場合はsession_expires_atのない bundle も拒否されます。タイムスタンプはすべての SDK でミリ秒の精度で比較されます。この変更の前に署名された bundle は、セッションの最大継続時間のないポリシーのもとでは以前と同じように検証されます。 - 署名されていない署名ブロックが署名と矛盾することがありました。 今は
signature.signer.idが RPR のhuman_id、signature.signer.kidsが複合署名の kid、manifest_hashがマニフェストのハッシュ、hash_algがスキーマの許す 2 つのいずれかでなければなりません。signBundleV2とsign_bundle_v2は RPR のhuman_id以外の署名者 id を拒否します。Go のSignBundleV2と Rust のsign_bundle_v2は、すでに RPR からそれを取得しています。 - PQ チェックポイントが検証されていませんでした。 Merkle ルートや PQ 署名を変えたチェックポイントや、 マニフェストが列挙しているのに存在しないチェックポイントでも検証に成功していました。今は bundle が列挙 されたチェックポイントを過不足なく持ち、それぞれが自らの監査エントリーを対象とし、エージェントが両方の アルゴリズムで署名していなければなりません(V2-12)。
- Go と Rust の検証者は
session_nonceのない成果物や監査エントリーを受け入れていました。今は TypeScript と Python と同じく、すべてがマニフェストの nonce を持たなければなりません。 tests/interop/v2/bundle_vectors.jsonに新しいベクターを追加しました。それぞれ 1 つの欠陥について署名した もので、must_reject_bundlesが 35 件、署名されていない署名ブロックのmust_rejectの変異が 4 件、must_accept_bundlesの対照が 8 件です。ケースはverifier_policy_overridesを持つことがあります。lib/verify.jsはdcp verify-bundleの鍵を RPR のbinding_keysの中で固定し、署名に使った kid のすべての エントリーが固定された鍵を持つことを求めます。これにより、署名者をまずパスポートの中で探す公開済みの SDK 2.1.1 でも固定が有効です。@dcp-ai/express(dcpVerify)、@dcp-ai/openclaw(dcp_verify_bundle)、Python の FastAPI ミドルウェア(dcp_ai.fastapi.DCPVerifyMiddleware)は、どの署名も検証せずに V2 の署名済み bundle を 受け入れていました。確認していたのは bundle の構造とセッション nonce だけで(FastAPI のミドルウェアはbindingフィールドからcomposite_sig_validも設定していました)、署名のない bundle や偽造された bundle、 署名後に意図が変更された bundle も検証済みと報告されていました。今は 3 つとも、すべての V2 bundle を SDK の検証者(@dcp-ai/sdkのverifySignedBundleV2、dcp_ai.v2のverify_signed_bundle_v2)と Ed25519 / ML-DSA-65 / SLH-DSA-192f のレジストリで、DEFAULT_VERIFIER_POLICYに設定済みのポリシーを 重ねて検証します(verifierPolicy、DCPVerifyMiddlewareの新しい引数verifier_policy、後述の OpenClaw の オペレーターのポリシー)。requireHybridはhybrid_requiredより下のリスク階層をすべてそこまで引き上げ (オペレーターのpq_onlyはpq_onlyのまま)、risk_overridesのないdefault_modeはすべての階層に 適用されます。検証者のエラーと警告が返され、composite_sig_validはその結果から得られます。@dcp-ai/sdk2.2.0 が npm に公開されるまで、2 つの TypeScript パッケージはワークスペースの SDK ("@dcp-ai/sdk": "file:../../sdks/typescript")に依存します。その検証者には上記の修正が入っています。CI は テストの前にそれをビルドし、3 つともtests/interop/v2/bundle_vectors.jsonのすべてのケースに、そのverifier_policy_overridesのもとで合格します。公開するには先に依存関係を^2.2.0に上げる必要があります。publish-integrations.ymlは、ローカルパスに依存するパッケージを拒否するようになりました。- 同じ 3 つの検証者は、V2 と判定されなかった bundle をすべて、検証者のポリシーにかかわらず V1 の検証者に
回していました。V1 の bundle(Ed25519 の署名が 1 つで、耐量子の署名はない)は
requireHybridやhybrid_requiredのポリシーを通り抜け、バージョンを判定できない bundle は V1 として試されていました。 今は、VERIFICATION.md V2-10 が古典のみの bundle を受け入れる場合にだけ V1 の bundle を受け入れます。 すなわち、allow_v1_bundlesが真で、requireHybridが無効で、V1 パスポートのrisk_tierに対する ポリシーのモードと、V1 の意図とポリシー決定のセキュリティ階層のモード(V1 のrisk_scoreは 0 から 1 で、 1000 倍する。ない場合はelevatedとみなす)のうち厳しい方が、classical_onlyまたはhybrid_preferredである場合です。DEFAULT_VERIFIER_POLICYのもとでは、V1 の適合性テストの bundle (standard 階層のsend_email)は合格し、同じ bundle で意図をinitiate_paymentにしたものは拒否されます。 バージョンを判定できない bundle は拒否されます。 @dcp-ai/openclaw:dcp_verify_bundleは、呼び出す側のモデルが制御するツールパラメーターverifier_policyから検証ポリシーを取り、失敗した結果とともに、検証されていない bundle のagent_idとhuman_idを返していました。今はポリシーがオペレーターのもの(register(api, { verifierPolicy })または新しいconfigureVerifier、DEFAULT_VERIFIER_POLICYに重ねる)です。 パラメーターはポリシーをより厳しくすることしかできません(階層ごとにより厳しいモードにする。pq_onlyと それ以外のモードを組み合わせるとhybrid_requiredになり、モデルがオペレーターの求める古典署名を外すことはできない。require_*は有効にすることだけ、allow_v1_bundlesは無効にすることだけができ、その他のフィールドは エラー)。結果はverification_modeを返し、エージェント、プリンシパル、セッションを示すのは bundle が検証に成功した場合だけです。@dcp-ai/express: 判定のキャッシュはsignature.composite_sigをキーとし、すべてのミドルウェアで共有されて いました。そのため、キャッシュ済みの署名を持つ別の bundle や、より厳しいポリシーを持つミドルウェアが 「検証済み」の判定を再利用していました。さらに、キャッシュは際限なく大きくなり、セッションや鍵が期限切れに なった後やエージェントが失効した後も、TTL の間ずっと判定を保持していました。今は各ミドルウェアが独自の キャッシュを持ち、キーは bundle の正規形の SHA-256(canonicalizeV2。JSON.stringifyがnullのように 出力していた1e999を含むものなど、正規形のない bundle は検証されるがキャッシュされない)で、cacheMaxEntries(新規、既定値 1000)個までの bundle を保持し、最も長く使われていないものから追い出します。 エントリーは、TTL、マニフェストのsession_expires_at、RPR のexpires_at、パスポートのすべての鍵と RPR の すべてのバインディング鍵のexpires_atのうち、最も早いもので期限切れになります。深く入れ子になった bundle で 500 が返ることはなくなりました。@dcp-ai/express:checkRevocationはエージェントとそのパスポートの鍵についてだけ問い合わせ、黙って フェイルオープンしていました。今は、キャッシュヒットを含むすべてのリクエストで、RPR のすべてのバインディング 鍵と bundle の署名の古典と PQ の kid についても問い合わせます。答えの得られない問い合わせ(サービスに到達 できない、2xx 以外の応答、JSON でない本文やrevokedを持たない本文)では、既定では引き続きリクエストを 通します。新しいrevocationFailClosed: trueを指定すると拒否します。@dcp-ai/express: 未知のオプションやverifierPolicyのフィールド(defaultMode)、誤った型の値 (allow_v1_bundles: "false")は無視され、既定値が有効のままになっていました。今はミドルウェアの作成時に 例外を投げます。dcp_ai.fastapi: Python の 4300 桁の制限を超える整数を含む、または入れ子が深すぎるX-DCP-Bundleヘッダーや、検証者にとって深すぎる bundle で 500 が返っていました。今は 403 を返します。 リストでないpq_checkpointsは拒否されます(チェックポイントなしとして読まれていました)。verifier_policy={"risk_overrides": None}は、default_modeをすべての階層に適用する代わりに既定の階層を 保つようになり、未知のリスク階層は例外を投げます。dcp_versionは強制されないことを文書に記しました。- 3 つの README に「検証済み」の意味を記しました。bundle が内部で一貫しており、bundle 自身が列挙する鍵で
署名されているということであり、検証者がプリンシパルの鍵を固定しない限り(どのミドルウェアもまだできない)、
プリンシパルが誰かを証明するものではありません。また、
verifier_idを伴うrequire_audience_bindingは、 リプレイを想定された検証者に限定します。 - Go と Rust の検証者は、マニフェストがコミットしているにもかかわらず、マニフェストと異なる
session_nonceを 持つ監査エントリー(または PQ チェックポイント)を受け入れていました(spec/VERIFICATION.mdV2-4: nonce を 持つすべての成果物と監査エントリーはマニフェストの nonce を共有する)。今は両方とも TypeScript と Python と 同じように証跡とチェックポイントを確認し、エラーはSession nonce mismatch in audit_entries[i]です。共有ベクターはaudit_entry_session_nonce_differsです。 - Rust の検証者は
manifest.canonicalization_profileをまったく確認せず、Go の検証者は文字列でない値を無視して いたため、bundle はどの検証者も実装していないプロファイルを名乗ることができました (spec/CANONICALIZATION_PROFILE.md§ 4、V2-3)。今は両方とも、TypeScript と Python と同じく、"dcp-jcs-v1"以外の値をすべて拒否します。共有ベクターはcanonicalization_profile_unknownとcanonicalization_profile_not_a_stringです。
追加¶
- 外部適合性キットに性能ベースラインのツール
tools/conformance-perf.js(契約dcp-ai-perf/1)を追加しました。このチェックアウトの 5 つの SDK の規範的な V2 検証器を、コミット済みの 6 つのワークロード(ハイブリッドのバンドル、無効な Ed25519 署名と ML-DSA-65 署名、3 つの二次 SHA3-256 のケース)について、同じ入力バイト列、ポリシー、検証時刻で測定します。 SDK ごとに公開エントリーポイントを通る 1 つのインプロセスの子プロセスを使い、ウォームアップと計測をラウンドロビンで行い、すべての呼び出しを確認します。すべてのサンプルを保持し、最近接順位の統計を付けます。 測定対象をビルドし、SDK ごとにソース、マニフェストとロック、成果物のハッシュ、ツールのバージョンを記録します(--no-buildは差異や欠落を拒否します)。速度の閾値、ランキング、割り当てた割合はなく、結果はローカルにとどめます。CI はネイティブのジョブでセルフテストと 5 つの SDK のスモーク実行を行います。 - Rust(
dcp_ai::v2::types)と Go(v2)の SDK にRawAuditEventV2を追加しました。受信した V2 の監査エントリーをデコードしたとおりに保持し、未知のメンバーも含め、あらゆる深さの各メンバーの有無とnullを保つため、dcp-jcs-v1 の正規化器が受け入れる限り、正規化されたバイト列、prev_hash、マークルの葉は入力のものと同じです。 Rust はデコードされたserde_json::Valueを保持し(オブジェクト以外にはRawAuditEventError)、Go はバイト列をそのまま、入力時と出力時にコピーして保持し、厳密に 1 つの JSON オブジェクト以外を拒否します。どちらも修復や再署名は行わず、無効な証拠は同じ理由で無効のままです。 既存のAuditEventV2とAuditEvidenceV2は変わらず、転送には損失があることを文書化しました(明示的なnull、未知のメンバー、nullになる存在しないpq_checkpoint_ref)。 新しい共有ベクトルtests/interop/v2/audit_entry_roundtrip_vectors.jsonは、手書きの dcp-jcs-v1 テキストを持つ 14 のエントリー(TypeScript、Python、Go、Rust の正規化器が再現します)と、新しい型が同じエラーで拒否し続ける変更を持つ署名済みバンドルを提供します。Go のバンドルビルダー、V1 の型、Python のAuditEventV2モデルは変わりません。 - 外部適合性キットのエビデンスカタログ(契約
/2)に--assessment verdictを追加しました。error_containsを持つ 146 件の拒否をverified: falseだけで判定し、それ以外の規則、制御、終了コードは変えません。これにより、判定が正しく独自のメッセージを返す実装がそれを示せます。 文言は診断として報告されます(matched、differs、no_message、または理由付きのnot_evaluated)。これらの各ケースはspec/VERIFICATION.mdの手順を示し、ランナーは実行前にそのアンカーと、すべての制御が単純な肯定ケースであることを確認します。 レポートは/2の wire の契約とは別にdcp-ai-conformance-assessment/1を宣言し、カタログの文章をcatalog_claimとcatalog_limitsに残します。オプションなし、または--assessment legacyでは判定とレポートは変わらず、/1と/3のカタログはこのオプションを拒否します。 カタログ、フィクスチャ、ラッパーは変わりません。CI は 5 つのラッパーをすべて必須にしてこの評価を実行します。 - 外部の適合性キット:オプトインのアドミッションのカタログ
--catalog admission(契約dcp-ai-conformance-external/3、tools/conformance/external-admission-catalog.json、140 ケース:admission_vectors.jsonの 65 の結果のベクトル、71 の設定のケース、 ベクトルの入力から組み合わせた 4 つのケース)。TypeScript、Python、Go、Rust のラッパーは、SDK の組み合わせたアドミッションの関数と 読み込み関数を通じて、リクエストのnowで答えます。判定は、フィールドの型、spec/profiles/admission の規則(action_authorizedはfalse、admittedはコードが 1 つも加えられなかったときに限る)、正確なフィールド、段階ごとの生のコードの順序とその繰り返しを 確認します。否定のケースは、その対照が合格した場合にだけ数えられます。答えは射影であり、内包する検証は判定しません。WASM の ビルドにはアドミッションの API がなく、エミュレートしません。CI は判定のセルフテスト(60)、ラッパーのテスト(26、4 つの ラッパーが必須)、そして 4 つのラッパーそれぞれで 140 ケースを実行します。証拠のセルフテストの偽の実装は、TypeScript の ラッパーに非同期の spawn で届くようになり、期限と終了の確認を伴います:9 MB のリクエストを渡す同期の spawn が期限まで 待ち続けるのが観察されたためです。/1と/2は変わりません。 - 正規化の候補:
dcp-jcs-v1の側のゲート 7 を測定。 新しい公開フィクスチャtests/interop/candidate/gate7-v1-negatives.jsonは、単位の 8 つのクラスそれぞれの欠陥を、18 のバイトの位置で、dcp-jcs-v1の凍結した 2 つの基準に注入します。制御としての 2 つの基準を含めて 38 ケースです。 5 つの実装の 10 の構成について、推論した期待値を記録しています。TypeScript、Python、Go、Rust の SDK と、Node 上の WASM パッケージです。 それぞれの新しいテストが 380 件の比較を実行します。実験的な検証器は、同じバイト列、時計、ポリシーで、同じ実装の現在の経路の結果を返さなければならず、両方が期待値と一致しなければなりません。 エンベロープの 3 ケース(30 件の確認)は別の境界として扱い、等価性は主張しません。標準ライブラリだけの厳密なチェッカーとその陰性の制御は、CI の適合性のジョブで実行します。 記録表はゲート 7 をサンプルで満たしたとしています。テストと文書だけの変更で、SDK の API、プロファイル、既定値、dcp-jcs-v1は変わりません。候補は実験的でオプトインのままで、何も公開しません。 docs/proposals/canonicalization-candidate/README.md を参照してください。 - 外部適合性ランナーの証拠カタログ:マークルと署名の検証。
--catalog evidenceは、任意で選ぶカタログ(tools/conformance/external-evidence-catalog.json、契約dcp-ai-conformance-external/2、241 ケース)をコミット済みの公開フィクスチャに対して実行します。 葉が 1、2、3、5 枚の正確な二重マークルルート、コミット済みの攻撃と決定的な改変を含む複合署名と古典署名のみの署名の検証、各ケースのコミット済みのオーバーライドを適用したdefault_verifier_policyによるbundle_vectors.jsonの規範的な V2 署名済みバンドルの検証、二次 SHA3-256 ベクターを、すべて固定したverification_timeで扱います。 陰性ケースは対照が合格した場合にだけ数えられ、エラーを伴うverified: true、error、unsupportedは決して合格になりません。 5 つのラッパーはどちらの契約も受け付けます。既定のカタログ、契約/1とその 38 ケースは変わりません。 CI は 241 ケースとセルフテストを 5 つすべてのラッパーで実行します。合格は受け入れ、信頼、認可のいずれでもありません。 「修正」のwasm_dual_merkle_rootの修正を除き SDK の変更はなく、パッケージも公開しません。 tools/conformance/README.md を参照してください。 - 外部適合性ランナー向けの Go、Rust、WASM のラッパー。
tools/conformance/wrappers/build.mjsは、このチェックアウトから Go SDK、Rust SDK、Rust SDK の WASM ビルドのラッパーをビルドします(-mod=readonly、--locked。 SDK のマニフェストやロックファイルは変わりません)。 各ラッパーは実際の API で同じ 38 ケースを実行し、正規化関数を 1 回だけ呼び、文書化された拒否だけを拒否として扱います。 WASM のラッパーはブラウザーではなく Node 上で実際の.wasmを実行し、エクスポートが結果の中で返す{"error": …}との衝突を保守的に扱います。 CI は 3 つをビルドし、必須のジョブとして実行します。パッケージは公開しません。 tools/conformance/README.md を参照してください。 - 外部適合性ランナー(
tools/conformance-external.js)。 別のバージョン付きカタログ(tools/conformance/external-catalog.json、契約dcp-ai-conformance-external/1)を、argv として指定した任意の実装に対して、stdin の JSON リクエスト 1 つと stdout の JSON レスポンス 1 つで実行します。 対象はdcp-jcs-v1の正規化 30 ケース(コミット済みの 19 のedge_casesを含み、うち 3 つは拒否されなければならない)と SHA-256 / SHA3-256 のダイジェスト 8 ケースで、いずれもコミット済みの期待値を使います。@dcp-ai/sdkと Python のdcp_aiのラッパーを含み、CI は両方を実行します。 既存の適合性コマンド、カタログ、レポートは変わりません。合格が示すのは、この 38 ケースに合格したことだけです。 tools/conformance/README.md を参照してください。 - FastAPI の
cancel_on_disconnectが、ミドルウェアの順序にかかわらず動作するようになりました。去った クライアントへの ASGI 応答は、何のメッセージもない状態ではなく、空の499(「client closed request」: 登録済みの ステータスではなく、DCP のステータスでもない)、Content-Length: 0、Cache-Control: no-storeで終わります。 - これらは DCP の応答による 2 つの ASGI メッセージで、
http.disconnectを受け取った後にだけ送られ、接続を 続けているクライアントには決して送られません。DCP の外側にあるBaseHTTPMiddlewareはhttp.response.startを必要とし、以前は「No response returned.」で失敗していましたが、今は正常に完了し 499 を記録します。 - ネットワークに何が届くかはサーバー次第です。uvicorn(計測済み、h11 で 0.54)は、なくなった接続に対しては
何も書き込まず記録もしません。ASGI のもとでは、別のサーバーが
OSErrorのサブクラスを送出することがあります。 - アドミッションの
request.state.dcp_agentは、クライアントがまだいることが分かってから公開されるように なりました。そのため、去ったクライアントはアドミットされたコンテキストを残しません。オペレーター自身の コードが設定した値には手を触れません。 - 本文の途中で去ったクライアントにも、同じ終わり方になります(以前は何もありませんでした)。
- どの層の本当のエラーも引き続き伝播します。その他は何も変わりません。オプション、既定値、本文の上限、
スーパーバイザー、
DenyListWorkersは同じです。 - クライアントの切断(オプトイン):
@dcp-ai/expressのcancelOnDisconnect、dcp_ai.fastapi.DCPVerifyMiddlewareのcancel_on_disconnect=True。 - 何をするか。 アドミッション中にクライアントが本当に去ったとき、そのリクエストの、そしてそのリクエスト
だけの、監督下にあるソースの呼び出しをキャンセルします。その枠は、ソースが本当に終わるまで占有されたままです。
そのリクエストについてそれ以上は何も行わず、何も送りません。ハンドラー、
next、キャッシュへの書き込み、onFailure、応答のいずれもありません。 - Express。 去るとは、応答が送信前に閉じること、または本文が不完全なままリクエストが閉じることです。
正常なリクエスト自身の
closeは該当しません。- すべてのソース関数が監督下にあり、
checkRevocationがなく、キャンセルに対応するスーパーバイザーが 必要です。すなわち、このバージョンのスーパーバイザーの新しいrunWithSignal機能です(ESM と CJS、 両パッケージ)。 run、その 4 つの引数、version: 1は変わらず、古いパッケージのスーパーバイザーもオプションなしで 引き続き動作します。- 監督下にある呼び出しの判断は、シグナルが中断される前に一度だけ行われるようになりました。
close()に 再入する中断のリスナーは何も変えません。 - 新しい結果
cancelled、カウンター(stats().cancelled、型では省略可能)、テレメトリーの理由を追加しました。
- すべてのソース関数が監督下にあり、
- FastAPI。
max_body_bytes、監督下にあるすべてのソースの callable、同期のtenantcallable が 必要です。- ミドルウェアはアドミッション中に保留中の
receive()を 1 つ監視し、次の読み手に引き渡します。何も 2 回 読まれず、失われることもありません。また、完全な応答の後に送られるhttp.disconnectを、クライアントが 去ったとはみなしません。 - オプションありでは、本文の途中で去ったクライアントには 400 の代わりに何も返しません。
- 最初の形では、ミドルウェアはアプリケーションの他の
BaseHTTPMiddleware層を包む必要がありましたが、 その要件はなくなりました(上のエントリーを参照)。 SourceSupervisorとDenyListWorkersは変わりません。OpenClaw にはこのオプションはありません。
- ミドルウェアはアドミッション中に保留中の
- オプションなしでは何も変わりません。
dcp_ai.v2.DenyListWorkersとdeny_list_revocation_source(..., workers=...)(オプトイン): Python の 拒否リストのヘルパー向けの、実際のダウンロードスレッドの上限です(max_workersは 1〜64、max_workers_per_tenantは省略可能、オブジェクトごと)。各ダウンロードは専用の非デーモンスレッドで実行され、 枠を確保した後に開始し、ダウンロードが本当に終わったとき(タイムアウト、キャンセルされた呼び出し、C3 の スーパーバイザーの期限、閉じたイベントループの後も含む)にだけ枠を解放します。空き枠のない呼び出しは、 キューも接続もなしに、ただちにREVOCATION_UNAVAILABLEを受け取ります。ダウンロード、本文の確認、解析、 エラーはオプションなしの場合と同じです。timeoutの後に届いた、または使われた結果はREVOCATION_UNAVAILABLEです。close()は実行中のダウンロードを待つことも止めることもせずに新しい ダウンロードを拒否します。stats()は URL、テナント、ヘッダーを含みません。フォークしたプロセスでは、親の ロックに触れずに拒否します。プロセスの終了は、asyncio.to_threadと同様に、まだ実行中のダウンロードを 待ちます。DNS、TLS、urllib を止めるものはありません。workersなしでは何も変わりません。timeoutの ドキュメントを修正しました。それが制限するのは各ソケット操作と本文の読み取りであり、DNS の解決や 少しずつ届くステータス行ではありません。- ソースのスーパーバイザー(C3)のもとでの失効の確認(オプトイン)。対象は
@dcp-ai/express、@dcp-ai/openclaw、dcp_ai.fastapi.DCPVerifyMiddlewareです。これまで拒否されていたsupervise: { revocation: true }/supervise={"revocation": True}は、strict-v1 の失効ソースをスーパーバイザーのもとで実行し、revocationTimeoutMs/revocation_timeoutを期限とします。期限はタイマーの範囲(1〜2147483647 ms の整数、 最大 2147483.647 s)に制限されます。superviseは信頼の期限、revocation、またはその両方を受け付けるため、 静的な信頼セットでも失効の確認を監督できます。信頼と失効の呼び出しはスーパーバイザーの容量を共有し、枠は そのソースが本当に終わったときにだけ解放されます。応答は変わりません。タイムアウト、空き枠なし、閉じた スーパーバイザーは、失敗したソースと同じREVOCATION_UNAVAILABLE(Express と FastAPI では 403)になり、REVOCATION_INVALIDのエラーは期限の前にだけ有効です。TypeScript のソースは(subjects, { tenant, signal })を受け取り、denyListRevocationSourceはそのシグナルで fetch も中断し、 テレメトリーはsource: 'revocation'を報告します。OpenClaw のconfigureVerifierは、どのソースを監督して いるかにかかわらず、呼び出しが進行中のスーパーバイザーの置き換えを拒否します。FastAPI には非同期のrevocation_sourceが必要です。オプションありの場合だけの動作の変更: 自らのキャンセルを抑止する FastAPI の ソースは、遅れて届いたスナップショットではなく、期限の時点でREVOCATION_UNAVAILABLEになります。制限 されないもの: ソースが独自に始める処理、たとえばdeny_list_revocation_sourceのasyncio.to_threadワーカーで、その I/O はキャンセルされません。オプションなしでは何も変わりません。 dcp_ai.fastapi.DCPVerifyMiddleware: 非同期のtrusted_principalsに対する期限と容量(オプトイン)。dcp_ai.fastapiからだけエクスポートされるSourceSupervisor(max_in_flight=..., max_in_flight_per_tenant=None)と、supervise={"trust_timeout": seconds}を伴うsource_supervisor(両方をあわせて使う)。ソースは スーパーバイザーが所有する Task として実行されます。期限の後に届いた信頼セット(loop.time()で、到着時と 使用時に確認)、空き枠のない呼び出し(キューなし)、閉じたスーパーバイザー、別のイベントループに結び付いた スーパーバイザーは、失敗したソースと同じ 503 になります。枠は Task が本当に終わったときにだけ解放されます。close(drain_timeout)とstats()を提供します。これらのオプションとともに静的または同期のtrusted_principalsを使うとAdmissionConfigErrorを送出します。この最初の段階では{"revocation": True}も同様でしたが、今は受け付けます(上の失効のエントリーを参照)。スーパーバイザーは イベントループごとに 1 つです。キャンセルを無視するソースを止めたり、CPU を隔離したりはしません。これらの オプションなしでは何も変わりません。@dcp-ai/expressと@dcp-ai/openclaw:trustedPrincipals関数に対する期限と容量(オプトイン)。createSourceSupervisor({ maxInFlight, maxInFlightPerTenant?, onSourceEvent? })がスーパーバイザーを作り、supervise: { trustTimeoutMs }を伴うsourceSupervisorがそれを適用します(両方をあわせ、trustedPrincipalsを関数として使う)。その場合、関数は{ tenant, signal }を受け取ります。 到着時に単調時計で測って期限の後に届いた信頼セットは使われず、空き枠のない呼び出し(キューなし)や閉じた スーパーバイザーも同様です。結果は失敗したソースと同じです(TRUST_SOURCE_FAILED、Express では 503)。 枠は関数が本当に終わったときにだけ解放されます。容量はスーパーバイザーのオブジェクトごとで、両パッケージと その ESM、CJS のビルドの間で共有できます。close({ drainMs })とstats()を提供し、カウンターはNumber.MAX_SAFE_INTEGERで止まります。OpenClaw のconfigureVerifierは、そのスーパーバイザーのもとで 始まった呼び出しが進行中である間(ソースを呼ぶ前も含む)や、そのソースがまだ実行中である間は、close()の 後であっても、スーパーバイザーの置き換えや削除を拒否します。ソースの処理を止めたり、CPU を隔離したりは しません。これらのオプションなしでは何も変わりません。この最初の段階ではsupervise.revocation: trueは拒否され、失効の確認はrevocationTimeoutMsのままでしたが、今は受け付け ます(上の失効のエントリーを参照)。dcp_ai.fastapi.DCPVerifyMiddleware(max_body_bytes=...): リクエスト本文に対するバイト単位の上限 (オプトイン)。既定はNoneで、以前と同じく上限なしです。正の整数でなければAdmissionConfigErrorCONFIG_INVALID_VALUEになります。この場合、ミドルウェアは、bundle がヘッダーにある場合やrequire_bundle=Falseの場合も含め、まず本文を読みます。上限を超えるContent-Length、または上限を超えて 受信したバイト(Content-Lengthなし、チャンク形式、または誤った値)は、残りを受信せず、解析、信頼の解決、 検証、ルートへの到達もせずに413を受け取ります。不正または重複したContent-Length、送信中の切断は400を受け取ります。上限内の本文は以前と同じように処理され、引き続きルートに届きます。制限するのは 受信したバイトであり、展開、JSON の深さ、時間ではありません。これはデプロイ上の制限であり、プロトコルの 一部ではありません。このオプションには、ミドルウェアで読んだ本文をルートに引き渡す Starlette 0.28.0 以降が 必要です。それより古い、または特定できない Starlette では、ミドルウェアの構築時にAdmissionConfigErrorCONFIG_INVALID_VALUEを送出します。パッケージの最小バージョンは変わらず、オプションなしでは何も確認しません。- アドミッション: 信頼されたプリンシパルと
strict-v1プロファイル(spec/profiles/admission、docs/ADMISSION.md)。検証済みの bundle が証明するのは、完全性と、bundle が列挙する鍵による署名です。 オペレーターの信頼セット(schemas/v2/principal_trust_set.schema.json)により、検証者は、bundle の プリンシパルの署名(RPR とマニフェスト、古典と PQ)を検証した鍵が、そのhuman_idの信頼された有効な鍵で ある場合にだけ bundle をアドミットできるようになりました。strict-v1(schemas/v2/admission_profile.schema.json)は、オペレーターが固定する要件を加えます。V2 のみ、すべての 階層でハイブリッド署名、セッションバインディング、オペレーターのverifier_idと等しい署名済みのintended_verifier、最長 300 s の署名済みセッション、そしてエージェントと検証済みのすべての署名者の鍵を 対象とする、作成から 300 s 以内の失効スナップショット(schemas/v2/revocation_snapshot.schema.json)です。 その設定は要件を厳しくすることしかできず、弱める値はCONFIG_PROFILE_CONTRADICTIONになります。結果はverifiedを保ち、principal_trust、profile_compliance、admitted、recorded_decision、trust_set_version、コード付きのerrors、常にfalseのaction_authorizedを加えます。アドミッションは 行動を認可しません。 - SDK: TypeScript(
admitSignedBundleV2、evaluateAdmissionV2、createPrincipalTrustStore、resolveStrictV1Profile、revocationSubjects、revocationSnapshotFromDenyList)、および Python、Go、 Rust の同じ関数。4 つの検証者は省略可能な時計を受け取り、署名の各構成要素をどの鍵で検証したか (signer_keys)を報告します。Rust では、V2VerificationResultは 10 個のフィールドを保ち、verify_signed_bundle_v2/verify_signed_bundle_v2_with_policyは型を保つため、それらに対して ビルドしたコードは引き続きコンパイルできます。鍵は新しいverify_signed_bundle_v2_atから得られ、これはV2VerificationDetails(#[non_exhaustive]。同じ検証による結果をresultとして、およびsigner_keys)を返します。アドミッションはこれを受け取って返し、その JSON は結果のフィールドの後にsigner_keysが続く形です。 - インテグレーション:
@dcp-ai/expressのdcpVerify、dcp_ai.fastapiのDCPVerifyMiddleware、@dcp-ai/openclawのconfigureVerifierは、trustedPrincipals、profile、revocationSource、 およびミドルウェアではオペレーターのtenant関数を受け取ります。リクエストがルートに届くのは アドミットされた場合だけです。例外を投げる、または有効な信頼セットを返さない(undefined、null、 不正なセット)信頼関数はリクエストを拒否します。ミドルウェアでは503、OpenClaw ではadmitted: falseです。Express のキャッシュは、bundle、ポリシー、テナントをキーとして暗号学的な検証だけを保持します。 信頼、プロファイル、失効はリクエストごとに評価されます。denyListRevocationSourceは完全な拒否リストを 読みます。失敗した、またはタイムアウトしたソースはリクエストを拒否します。 - リファレンスの検証者、サーバー、CLI:
lib/verify.jsのadmitSignedBundle、DCP_TRUSTED_PRINCIPALS_FILE、DCP_ADMISSION_PROFILE_FILE、DCP_REVOCATION_LIST_URLで設定するPOST /v2/admit、およびdcp admit-bundle。 tests/interop/v2/admission_vectors.json: 手書きの期待結果と各ケースが確認する規則を持つ 65 ケースと、 49 個の設定のケース。4 つの SDK とnpm run conformanceが実行します。- Rust SDK: V2 の bundle のネイティブな構築と署名、
dcp_ai::v2::bundle。build_bundle_v2(&rpr, &passport, &intent, &policy, &audit_entries, session_nonce)は各payload_hashと、すべての成果物と 監査エントリーのsession_nonceを確認し、両方の監査 Merkle ルートを含むマニフェストを書き込みます(空の 証跡では、Go と同じく 64 個のゼロのルートになります)。sign_bundle_v2(bundle, &classical, &pq)は、Go のSignBundleV2と同じく、signer.idを RPR のhuman_idとしてマニフェストに 複合署名します。Go のものと同様、このビルダーはまだ PQ チェックポイントを受け取りません。相互運用性 マトリクスの Rust エージェントは、bundle を手作業で組み立てる代わりにこれらを使います。 tools/interop-matrix: 4 つの SDK の間のライブの相互運用性。SDK ごとに 1 つのエージェントプロセス (TypeScript、Python、Go、Rust)がアイデンティティを作り、意図を宣言し、行動し、市民権の bundle に署名 します(DCP-01 から DCP-03)。他のすべてのエージェントとリファレンスの検証者lib/verify.jsが、既定の ポリシーとhybrid_requiredのもとで、手を加えない状態と、転送中の 7 種類の改ざん(意図の変更、監査 エントリーの並べ替えや削除、セッションのつなぎ合わせ、bundle の署名やパスポートの差し替え、PQ 署名の 剥ぎ取り)の後で、それらを検証します。エージェントが共有するのは、オーケストレーターが中継するメッセージ だけです。.github/workflows/interop-matrix.ymlが、すべてのプルリクエストと毎晩これを実行します。@dcp-ai/google-a2a2.1.0: 署名済みの DCP Agent Passport が A2A の Agent Card の中で運ばれるように なりました。passportToAgentCard(signedPassport, url)(またはattachPassportToAgentCard(card, signedPassport)) は、A2A 自身の拡張の仕組みであるcapabilities.extensionsのhttps://dcp-ai.org/a2a/extensions/passport/v2の下にSignedPayload<AgentPassportV2>を置きます。verifyAgentCardPassport(card)はそれをオフラインで検証し(ペイロードのハッシュ、パスポートが列挙する 有効で期限切れでない鍵による AgentPassport コンテキストのpq_over_classical複合署名、status: active、 同じエージェントを示すmetadata.dcp_agent_id)、不正な形式のものがあればフェイルクローズします。 カードがパスポートを持つ場合、agentCardToPassportはひな形ではなくそのパスポートを返します。パッケージは TypeScript になりました(dist/のビルド、CI での vitest のテストスイート)。@dcp-ai/anthropic-mcp2.1.0: MCP のツール呼び出しに対する署名付きのレシート。withDcpReceipt(name, handler, { identity })は任意の MCP ツールのハンドラーを包みます。呼び出しは Intent(DCP-02)に分類され、ツールの実行前に 複合署名され、ポリシーが判断します(approve ではツールを実行し、escalate と block では実行せずにisErrorの 結果を返し、例外を投げるハンドラーはoutcome: "failed"になります)。そして 1 つの監査エントリー(DCP-03)が引数と結果の SHA-256 を記録します。_meta.dcp_receiptのレシートは通常の DCP v2.0 の署名済み bundle なので、どの DCP の検証者でもオフラインで 確認できます。verifyDcpReceiptはさらに、呼び出し側が見た引数と結果から証拠のハッシュを再計算し、ツール名を 確認します。createReceiptIdentityは、テストや初回の実行のためにセッションのアイデンティティ(Ed25519 + ML-DSA-65 の鍵、署名済みの RPR とパスポート)を発行します。パッケージは TypeScript になり(dist/のビルド、 CI での vitest のテストスイート)、dcp_verify_bundleは構造の確認ではなく本物のverifySignedBundleV2を 実行します。使われていなかった入力security_tierは削除しました。tests/interop/v2/bundle_vectors.json: 拒否のケースを 28 件追加しました(must_rejectの変異 5 件、must_reject_bundles23 件)。v2.10 のラウンドの脆弱性ごとに 1 件ずつで、4 つの SDK の検証者(Python を含む)が すべての検証モードで実行します。composite_sigをまったく持たない成果物(V2-8)、dcp_bundle_versionが1.0と3.0(V2-1)、UTC でないオフセットで期限切れになった鍵、パスポートの鍵の不正なexpires_at(存在しない 日付、日付のみ、オフセットなし)と RPR の存在しない日付(V2-13)、意図がsecurity_tier: "routine"またはestimated_impact: "high"を宣言しているのに、意図やポリシー決定がelevatedを意味する古典のみの bundle (V2-10)、パスポートのrisk_tierにあるプロトタイプのキー(constructor、__proto__、toString、hasOwnProperty)と、action_type、estimated_impact、security_tierにあるconstructor(V2-9)、未知の、 または文字列でないcanonicalization_profile(V2-3)、別のsession_nonceを持つ意図、監査エントリー、 マニフェスト(V2-4)、一致しないマニフェストのハッシュ、監査ルート、チェーンのハッシュ(V2-3)です。tools/difffuzz: 変異させた同じ V2 の署名済み bundle を TypeScript、Python、Go、Rust の検証者(このチェック アウトからビルドした SDK ごとのシム)に通し、不一致、クラッシュ、タイムアウトがあれば失敗とし、各発見をtools/difffuzz/findings/に保存する差分ファザーです。シードはtests/interop/v2/の V2 の署名済み bundle です。 ミューテーターは、削除や null にしたフィールド、型の入れ替え、兄弟要素の入れ替え、base64 の文字の反転、 プロトタイプのキー、未知のキー、重複した成果物、数値と RFC 3339 の変種、大きすぎる文字列、深い入れ子、 キーの並べ替え(判定を決して変えてはならない)を扱います。.github/workflows/difffuzz.ymlが、すべてのプルリクエスト(300 回の反復)、workflow_dispatch、毎晩 (3000 回の反復)でファザーを実行します。- 4 つの SDK すべてで検証可能な委任チェーン(DCP-09 §3.5)。
schemas/v2/delegation_mandate.schema.jsonに 省略可能なフィールドparent_mandate_id、delegation_depth、sub_delegation({ permitted, max_depth })、minimum_security_tier、delegator_composite_sigを追加しました。ルートマンデートはhuman_composite_sigを 保ち、1 バイトも変わりません。サブマンデートはその代わりに、委任するエージェントが新しいドメイン分離 コンテキストDCP-AI.v2.SubMandate(domain-separation.{ts,py,go,rs}、interop_vectors.json)のもとで署名したdelegator_composite_sigを持ちます。verifyMandateChain/verify_mandate_chain/VerifyMandateChainは、 順序付けられたチェーンを人間までオフラインで検証します。人間の鍵によるルートの署名、親エージェントの鍵による 各段階の署名、親とのリンクと深さ、sub_delegation.permittedと祖先のmax_depthの最小値、同じhuman_id、 RFC 3339 の時点として比較する入れ子になった有効期間、縮小(actions_permittedとdata_classesが部分集合で あること、limitsが決して緩くならないこと、親にdata_classesがなければ子は追加できないこと、数値のlimitsは ±(2^53 − 1) の範囲の整数に限ること。その範囲を超えると、JSON の数値を倍精度で読む検証者とすべての 桁を保持する検証者とでマンデートの内容の解釈が食い違うため、そうした制限はどの深さでもnot comparableに なる)、親を決して下回らないminimum_security_tier、そして失効です。失効した祖先は、そのすべての子孫を無効に します。結果にはチェーンの実効的な階層(チェーン上のminimum_security_tierの最大値)が含まれます。未知の もの、深さに対して欠けているもの、比較できないものは、すべてフェイルクローズします。署名の鍵は検証時刻にactiveで期限切れでない必要があり、マンデートの署名はpq_over_classicalでなければなりません。 - ルートのビルダーの隣にサブマンデートのビルダーを追加しました。
createSubMandate/create_sub_mandate/CreateSubMandate、およびルートのビルダーのsub_delegation/minimum_security_tier(Rust ではcreate_delegation_mandate_with_optionsとMandateChainOptions)です。 computeSecurityTier/compute_security_tier/SecurityTierInput.MandateChainTier/compute_security_tier_with_floor、およびルートにあるコピーlib/security-tier.js(computeSecurityTier(intent, policyDecision, mandateChainTier))は、検証済みのチェーンの実効的な階層を、階層を引き上げることしかできない 省略可能な入力として受け取ります(仕様 §14.2)。Go では、空のMandateChainTierはチェーンなしを意味し、階層で ないその他の名前はelevatedとみなされます。bundle の検証者はまだこれを読みません。bundle には、その マンデートチェーンを運ぶフィールドがないためです。tests/interop/v2/mandate_chain_vectors.json(sdks/typescript/src/__tests__/generate-mandate-chain-vectors.tsが生成): すべての SDK がその深さと実効的な 階層とともに受け入れなければならない深さ 1 と 2 のチェーン、すべての SDK が拒否しなければならないチェーン (行動の拡大、データクラスの追加、制限の緩和、倍精度では表せないワイヤー上の整数として書かれた 2^53 や 2^53 + 1 の制限、親の範囲外の有効期間、max_depthを超える深さ、欠けている、または誤ったparent_mandate_id、引き下げられた階層、失効したルートや中間のマンデート、誤ったエージェントが署名した サブマンデート、両方の署名がある場合、誤ったdelegation_depthなど)、そして階層の下限のケースです。 4 つの SDK のテストスイートすべてがこれを実行します。- 正規化の候補
dcp-jcs-v2のための実験的なオプトインの API(docs/proposals/canonicalization-candidate、 §15–§18)。候補は規範的でなく、有効でもありません。dcp-jcs-v1が唯一の規範的で既定の正規化プロファイルで あり続け、既定値、ビルダー、署名者、検証者のいずれも変わりません。これらの API に到達するのは、TypeScript、 Python、Go、Rust、WASM でオプトインした呼び出し側だけです。 - 取り込み: 1 つの単位の元のバイト列を確認し(UTF-8、BOM、重複、±(2^53−1) の範囲の正確な整数、深さ 64)、 その正規のバイト列、またはクラスとオフセットを返します。
- ルーター: 単位をその転送形式から取り出し、プロファイルを読んで判断します。拒否する、名前付きの履歴用
デコーダーを通じて
dcp-jcs-v1に委ねる、または候補を選ぶ、のいずれかです。 - 検証者: 元のバイト列から、多くとも 1 つの検証者で検証します。
dcp-jcs-v1には現行の検証者、候補にはdcp-jcs-v2だけを受け入れる現行の検証者を使います。検証済みの bundle は信頼もアドミッションも与えません。 - 生成者: 元のバイト列、または厳密に確認したホストの値から、成果物(
experimentalCandidateSignPayloadと その同等物)と、マニフェストがdcp-jcs-v2を示す bundle(experimentalCandidateSignBundle)に署名します。 入力の領域や形式による拒否は、どの署名者も呼ぶ前に発生します。鍵、レジストリ、プロバイダーのエラーは、 署名が作られた後に起こることがあります。 - テスト: 5 つの生成者 × 5 つの利用者の交差マトリクス(
tests/interop/candidate/phase4、全か無かの判定を 伴う 975 件の結果)とそのコストの測定で、新しいワークフローcanonicalization-candidate-matrixが実行し、 何も公開しません。ベクターはtests/interop/candidate/にあります。
変更¶
- 翻訳は
i18n/<locale>/の下に移り、移動しない英語の原文と同じパスに置かれます。es、pt-BR、ja、zh-CNについて、<dir>/<name>.<locale>.mdはi18n/<locale>/<dir>/<name>.mdになりました(388 ファイル)。移動で変わったのは リンクのパスだけで、移動したファイルのリンクと、英語の 10 文書の言語リンクです。各 SDK の英語の README は翻訳を 絶対 URL で参照するため、その言語リンクはパッケージ外のパスに依存しません。ドキュメントサイトは 5 言語すべてで URL、アンカー、言語セレクターを維持します。古いパスはmainにはもう存在せず、リダイレクト用の ファイルもありません。以前のコミットやタグでは、各ファイルは元のパスにあります。このツリーからパッケージ化される SDK と インテグレーションの npm パッケージの今後のバージョンには、翻訳された README は含まれません。公開済みのパッケージは 変更されず、その古い GitHub のパスへのリンクは古くなる可能性があります。ドキュメントのチェック(scripts/docs_i18n.py)は、 登録された翻訳ではないi18n/配下のファイル、翻訳に届かないi18n/へのリンク、英語の原文そのものに リンクしない翻訳の注記も拒否し、このリポジトリのmainブランチへのリンクをローカルのリンクと同じように検査します。 dcp-ai verify(@dcp-ai/cli)は、V2 の bundle(bundle.dcp_bundle_versionが "2.0"、またはbundle.manifestがある)を規範的な検証者で検証します。エンベロープと 4 つの署名済みペイロードを、パッケージに コピーが同梱されるschemas/v2で検証し、その後@dcp-ai/sdkのverifySignedBundleV2をDEFAULT_VERIFIER_POLICYと Ed25519、ML-DSA-65、SLH-DSA-192f のプロバイダーで実行します。規範以前の エンベロープ(トップレベルのdcp_version"2.0" やbundle_manifest、またはsignature.binding: "composite") は、それらの印が V1 や V2 の bundle にある場合も含め、他の何よりも先に拒否し、そのsignature.classical.valueのチェックは古典署名へのフォールバックなしで削除しました。.dcp/keys/ed25519_public.keyが存在する場合は、それが RPR のbinding_keysの中でプリンシパルの署名鍵を 固定します(空のファイルは拒否)。存在しない場合は bundle 自身の鍵を使い、署名は確認しますが、信頼や アドミッションは確認しません。V1 の検証は変わりません。dcp-ai signも変わらず、verifyが読まない形式であるsignatures[]に追記します。V2 の bundle にはsignBundleV2またはdcp sign-bundle --compositeで署名します。 パッケージは@dcp-ai/sdk^2.2.0を必要とし、ajvとajv-formatsを宣言するようになりました。dcp-ai verify(@dcp-ai/cli)が 0 で終了するのは VALID を出力したときだけです。V1 のファイルでは、Ed25519 の 署名が INVALID のとき、鍵がない、または使える署名がないとき(鍵があって署名がない、または空の場合も含め「No public key available」を出力)、ファイルが署名済みの bundle でないとき(真のbundleを持たないオブジェクト、配列、 プリミティブ)、これまで 0 で終了していたところを 1 で終了するようになりました。それらのメッセージは変わらず、 引数やファイルがない、不正な JSON、base64、誤ったサイズの場合も、引き続きそのエラーとともに 1 で終了します。 終了コード 0 を「実行された」と解釈していたスクリプトは、これらの場合に 1 を想定する必要があります。V1 の ファイルで終了コード 0 が意味するのは、正規化した bundle に対する Ed25519 の署名が検証できたことだけです。V2 の bundle では、スキーマと規範的な検証者に合格したこと(上記)を意味します。どちらもアドミッションの判断では ありません。- Go と Rust の V2 検証者:
accepted_classical_algsやaccepted_pq_algsを狭めるポリシーは、適用していない フィールドとして拒否され、そのもとではすべての bundle が失敗していました。今は TypeScript と Python と同じく 両方のリストを適用し(古典のリストはpq_onlyの場合を除く)、それらに含まれないアルゴリズムの署名は、検証者の ポリシーで受け入れられないものとして失敗します。また、strict-v1 が設定するallow_v1_bundles: falseも 受け付けます。これらは V2 の bundle しか検証しないため、このフィールドは何も変えません。以前に検証できた ポリシーは同じように動作します。 - リファレンスの検証者(
lib/verify.js、dcp verify-bundle、検証サーバーとその Docker イメージ)は、2.2.0 が npm に公開されるまで、ワークスペースの@dcp-ai/sdk(file:sdks/typescript、.npmrcのinstall-linksで パック)に依存します。そのため、79 個のmust_reject_bundlesベクターのうち 39 個を受け入れていた公開済みの 2.1.1 ではなく、このリリースの検証者の修正を実行します。ルートでnpm installする前にsdks/typescriptをビルドしてください。CI とdocker/Dockerfileはそうしています。公開するには、依存関係を^2.2.0に戻す必要があります。 lib/verify.js: スキーマの検証は、validateOneの呼び出しごと(V2 の bundle につき 5 回)にすべてのスキーマを 読み込んでコンパイルする代わりに、スキーマのルートごとに 1 つの Ajv を作り、各スキーマを初回の使用時に 1 度だけ コンパイルします。V2 の bundle のスキーマ検証は約 34 ms から 0.14 ms になりました(まだコンパイルを行う初回を 除いた 20 回の実行の中央値)。
修正¶
- 受け入れの変更:Go の
v2.VerifyPayloadHashが規範的なpayload_hashを確認するようになりました(mainのソースコード、未公開。Go v2.11.1 は欠陥を残したまま)。 以前は接頭辞のない 16 進の SHA-256 をpayload_hashと比較していたため、SignPayloadの出力とスキーマ上有効なすべての値(sha256:<hex>)に対してfalseを、接頭辞のないダイジェストに対してtrueを返していました。 現在は、payload_hashが"sha256:"の後にdcp-jcs-v1バイト列の SHA-256(小文字の 16 進数)を続けた値と完全に一致する場合にだけtrueを返します。これはSignPayload、schemas/v2/signed_payload.schema.json、TypeScript、Python、Rust のヘルパーが使う値です。 接頭辞のないダイジェスト、大文字の 16 進数、前後の空白、その他の形はすべてfalse, nilになります。 移行:payload_hashを受け取ったまま渡してください。PreparePayloadから作る場合は"sha256:" + hashと書きます。PreparePayloadは引き続き接頭辞のないダイジェストを返し(そのコメントで明記しました)、nilと正規化のエラーは変わりません。このヘルパーを使っていなかったバンドル検証器も変わりません。 このヘルパーが確認するのはハッシュの整合性だけで、署名、鍵、ポリシー、受け入れは確認しません。新しいsdks/go/dcp/v2/signed_payload_test.goを追加しました。 Go の README とAuditEvidenceV2のコメントでは、受信したバンドルを型付きの構造体にデコードするとevidenceのnullのメンバーと未知のメンバーが失われるため、保持して検証すべきなのは受信したバイト列であることも説明しています。 - 受け入れの変更:WASM の
wasm_dual_merkle_rootと@dcp-ai/wasmのdualMerkleRootが V2-11 の二重マークルルートを計算するようになりました(mainのソースコード、未公開。@dcp-ai/wasm2.1.1 以前は古いヘルパーのまま)。 このヘルパーは 2 つのダイジェストの 16 進テキストを連結してハッシュし、奇数のノードを繰り上げていたため、2 枚以上の葉ではルートがspec/VERIFICATION.mdV2-11(32 バイトの生のダイジェストを連結し、奇数の層では最後のノードを複製)とも、TypeScript、Python、Go、Rust の SDK とも一致しませんでした。 現在は Rust のコアv2::dual_hash::dual_merkle_rootに委譲します。 変更は複数の葉のルートに限りません。公開済みのヘルパーが生成した複数の葉のルートは V2-11 と互換性がなかったため変わります。32 バイトの 16 進ダイジェストでない葉は、テキストとしてハッシュされる代わりにエラーになります。ルートは常に小文字の 16 進数になるため、大文字で渡した 1 枚の葉は小文字で返るようになりました。 小文字で渡した有効な 1 枚の葉、結果の形式、空の配列と JSON でない入力に対するエラーは変わりません。 バンドルの検証は、WASM の検証器も含め、すでに正しい縮約を使っており、変わりません。変更はこのヘルパーに限られるため、以前のバンドルとその証拠を書き換えたり署名し直したりはしません。 新しい公開ベクターtests/conformance/v2/merkle_vectors.json(葉が 1、2、3、5 枚の場合と並べ替えた葉の正確なルート。 Python の標準ライブラリでオフラインに生成し、2 枚の葉の golden ルートを基準にしています)は、sdks/wasm/test/dual-merkle-root.mjsとsdks/rust/tests/dual_merkle_vectors.rsで確認します。 denyListRevocationSource(@dcp-ai/express、@dcp-ai/openclaw)が応答を開いたままにしていました。2xx 以外の 応答や、16 MiB を超えるContent-Lengthを宣言した応答は、本文を読みも閉じもせずに拒否されていました。応答は、 呼び出しが終わって枠が解放された後も開いたままで、タイムアウトや呼び出し側のシグナルが届かない状態でした。 さらに Node 22.15(undici 6.21.2)では、ヘッダーの後のガベージコレクションによって、fetch のシグナルが読み取り 中の本文に届かなくなることがありました。自身のタイムアウトもスーパーバイザーの期限も、まだ届き続けている本文を 止められなくなり、呼び出しは終わらずに枠を保持し続けました。今は、どの終了経路でも fetch を中断して本文を キャンセルし、自身のシグナルで読み取りを止め、リーダーを解放します。エラーコード、既定値、容量は変わりません。 何も読み捨てず、リモート側のクローズも待ちません。- リファレンスの CLI(
bin/dcp.js): パスは、指す先ではなく書かれたとおりの形で作業ディレクトリに制限されて おり、いくつかの読み書きはそのチェックを経ていませんでした。作業ディレクトリ内のシンボリックリンクや、別の ディレクトリへのパス(keys rotate --key-dir、governance sign-advisory --key-dir、governance verify-advisory --sigs)によって、コマンドが秘密鍵を含む外部のファイルを読むことが できました。出力パスにあるシンボリックリンクやハードリンク(keygen、keys rotate、recovery-setup、 ガバナンスのコマンド、V1 のsign-bundleの出力)によって、外部に書き込むことがありました。既存の秘密鍵の ファイルは広い権限のままでした。さらにdcp validate、conformance、V1 のsign-bundleは作業ディレクトリ からtools/*.jsを実行していたため、仕込まれたスクリプトが実行されていました。今はすべてのパスをシンボリック リンクを含めて解決し(リンク切れのものは拒否)チェックし、ユーザーのパスに対するすべての読み書きがそのチェックを 通り、ファイルは新しいファイル(O_EXCL、正確な権限)に書いてから対象に名前を変えて置き換え、CLI は自身の ツールを実行します。CLI は、コマンドの実行中に他のものが作業ディレクトリを変更しないことを前提としています。O_NOFOLLOWのない Windows でも、名前の変更はリンクを通して書き込むのではなく、リンクを置き換えます。 @dcp-ai/anthropic-mcpと@dcp-ai/google-a2a: エクスポート条件"types"が先頭にあったため、CommonJS の 利用者は ESM の宣言(dist/index.d.ts)を受け取り、TypeScript はnode16のもとでrequire()を TS1471 で 拒否していました。この条件を削除したため、requireはdist/index.d.ctsを、importはdist/index.d.tsを 受け取ります。@dcp-ai/sdk、@dcp-ai/express、@dcp-ai/openclawは、"import"と"require"の後にあって 一度も一致せず、ビルドのたびに tsup に警告させていた同じ条件を削除します。エクスポートに"require"のない@dcp-ai/wasmでは、Node がERR_PACKAGE_PATH_NOT_EXPORTEDで拒否するrequire()に対して、nodenextの もとで CommonJS の利用者に型を与えていました。今はそこでも TypeScript が TS2307 を報告します。- Go SDK:
VerifySignedBundleV2WithPolicyは、require_session_expiry、require_audience_binding、verifier_idを設定したポリシーのもとではすべての bundle を失敗にしていました。これらはverifier_policy.schema.jsonが列挙し、TypeScript と Python の検証者が適用するフィールドです。VerifierPolicyにそれら(RequireSessionExpiry、RequireAudienceBinding、VerifierID、ゼロ値で無効)を追加し、検証者は TypeScript と同じように適用します。session_expires_atのないマニフェスト、intended_verifierのない マニフェスト、verifier_id以外の検証者を宛先とするマニフェストは拒否されます。 - Rust SDK と
@dcp-ai/wasm:VerifierPolicyは、schemas/v2/verifier_policy.schema.jsonが列挙し、 TypeScript と Python の検証者が適用するrequire_session_expiry、require_audience_binding、verifier_idを 拒否していたため、そのいずれかを設定したポリシーではすべての検証が失敗していました。今は TypeScript と同じ ように適用します。require_session_expiryのもとではsession_expires_atのないマニフェストを拒否し、require_audience_bindingのもとではintended_verifierのないマニフェスト、またはverifier_idが設定されて いる場合は別の値を持つマニフェストを拒否します。Rust のBundleManifestにintended_verifierを追加しました。 - Python SDK の
dcp_ai.langchain(DCPTool.run、DCPTool.arun)とdcp_ai.openai(handle_dcp_tool_callのdcp_verify_bundle): どちらもすべての bundle を V1 の検証者に送っていたため、 V2 の bundle はすべて拒否され、V1 の bundle は検証ポリシーなしで受け入れられていました。今は V2 の bundle を、verify_signed_bundle_v2と 1 度だけ作る Ed25519 / ML-DSA-65 / SLH-DSA-192f のレジストリで、呼び出し側が設定する 検証ポリシー(DCPTool(verifier_policy=...)、handle_dcp_tool_call(..., verifier_policy=...)、DEFAULT_VERIFIER_POLICYに重ねる)のもとで検証し、検証者のエラーを返します。返すのはそれぞれ 500 文字までの エラー 20 件と警告 20 件までで、bundle が提供するテキスト(agent_id、不正なタイムスタンプ)の制御文字と書式 文字はエスケープします。これにより、bundle がモデルのコンテキストにメガバイト単位のデータや改行を入れることは できません。V1 の bundle が受け入れられるのは、FastAPI のミドルウェアの V2-10 の規則のもとでだけです。この規則は 今では 3 つの入口すべて(dcp_ai._verify_any)で共有され、ポリシー全体に拡張されました。ポリシーが V1 の bundle を許可し、ed25519 を受け入れ(accepted_classical_algsにあり、advisory_rejected_algsにない)、 オーディエンスのバインディング、セッションの有効期限、セッションの最大継続時間を求めず(V1 の bundle にはintended_verifierもセッションの期間もない)、そのリスク階層とセキュリティ階層について古典のみの bundle を 受け入れる場合です。FastAPI のミドルウェアも追加された条件を適用します。成果物がオブジェクトでない V1 の bundle、audit_entriesがオブジェクトのリストでない V1 の bundle は 3 つとも拒否し(FastAPI のミドルウェアは オブジェクトでないagent_passportに 500 を返していましたが、今は 403)、dcp_ai.verify.verify_signed_bundleは不正な形式の署名ブロック、鍵、監査証跡に対して例外を投げる代わりにエラーを返します。パスポートのagent_idや RPR のhuman_idが文字列でない(またはパスポートのpublic_key、status、capabilitiesの型が誤っている) V1 の bundle も、FastAPI のエージェントのコンテキストに届く前に拒否します。FastAPI のミドルウェアの 403 応答と そのコンテキストのwarningsは、ブリッジの出力と同じように制限しエスケープします。VerifierPolicyの インスタンスは dict と同じように検証されるため、model_constructで作られたものや代入で変更されたものが 不正な値を持つことはありません。また、risk_overridesが省いているリスク階層には、V2 の検証者と TypeScript SDK のresolveModeが解決するのと同じように、そのdefault_modeが適用されます(以前は、その階層の V1 の bundle は「is not low, medium or high」で拒否されていました)。同期の入口は、実行中のイベントループの中でも動作し (検証はワーカースレッドで実行)、プライベートなループで実行して、スレッドの現在のイベントループをそのまま 残します。DCPTool.arunは検証を await し、新しいaverify_bundle_tool_callは OpenAI のツール呼び出しの非同期 版です。どちらもtests/interop/v2/bundle_vectors.jsonのすべてのケースに合格します。 - Go SDK:
BundleManifestにintended_verifierがなかったため、そこにデコードして再びエンコードした マニフェストはこのフィールドを失い、署名が検証できなくなっていました。フィールドを追加しました (IntendedVerifier、空の場合は省略)。テストで、スキーマのすべてのフィールドを持つマニフェストを往復させます。 - Python SDK の
dcp_ai.crewai:DCPCrewのエージェントがクルーのセッション nonce を共有していませんでした。DCPCrewAgentは常に独自の nonce を生成していたため、nonce のないエージェントに対するクルーのチェックは 適用されず、各エージェントの監査エントリーはそれぞれ異なるsession_nonceを持っていました。今はクルーが、 自ら生成した nonce をまだ持っていて、まだ何も記録していないすべてのエージェントに自分の nonce を渡します。 エージェントに与えられた nonce や、後から設定された nonce はそのままです。 - Rust の
wasm機能と@dcp-ai/wasm:wasm_sign_bundle(signBundle)はcreated_at ""を書き、signer.idを書かなかったため、リファレンスの検証者、CLI、サーバーは、それが署名したすべての bundle を拒否して いました(created_at must match format "date-time"、signer must have required property 'id')。wasm_build_bundle(buildBundle)は、他のすべての SDK と違って SHA3-256 の監査の葉を SHA-256 で結合し、正規化できない監査エントリーを数えたまま飛ばしていました。今は両方ともbuild_bundle_v2とsign_bundle_v2を呼ぶため、buildBundleは、ペイロードと一致しないpayload_hashや、別のセッションの 成果物やエントリーも拒否します。sessionNonceがない場合、buildBundleはどの成果物も持たない nonce を生成して いたため、verifyBundleでさえ bundle を拒否していました。今は RPR のsession_nonceを使います。デモのexample.htmlは、wasm_build_bundleが一度も受け付けたことのない生のペイロードを渡していましたが、今は先に 各成果物に署名します。SignedBundleV2型はsigner.idを宣言します。 - Rust SDK:
Ed25519Provider::signは 32 バイト未満の秘密鍵でパニックしていました(wasm では JSON のエラーでは なくトラップ)。今はinvalid secret key lengthを返します。 - マンデートチェーン(4 つの SDK すべて): 親のエントリーがデータクラスを持つのに
data_classesを持たない サブマンデートのエントリーが縮小のチェックを通っていました。その場合、親のデータクラスにそれを縛るものは何も ありませんでした。今は、limitsのキーが欠けている場合と同じく拒否されます(data_classes for domain "<d>" missing)。 DCP-09 §3.5.2 の規則 5 がそう定めています。共有ベクターはdropped_data_classesです。 - Go SDK: 複数の goroutine から使われた
A2ASessionがプロセスをクラッシュさせていました(DecryptMessageでのfatal error: concurrent map writes)。セッションはミューテックスを持つようになったため、EncryptMessage、DecryptMessage、NeedsRekeyingを並行して実行できます。シーケンスは一意のままで、各メッセージは引き続き 1 度だけ受け入れられ ます。IntentV2にSecurityTierを、PolicyDecisionV2にResolvedTierを追加しました(どちらもスキーマで 省略可能で、空の場合は省略)。これにより、型付きのペイロードを使う Go の統合者がそれらを宣言できます。 tools/difffuzz:prototype_key_as_keyは__proto__を通常のプロパティとして代入していました。これはキーを 追加するのではなくプロトタイプを設定するため、これらの変異体は名乗っているキーを一度も持たず(循環によって実行が クラッシュすることもありました)、今は自身のキーとして定義します。起動できないシムや判定の合間に終了したシムは、 未処理のエラーではなくクラッシュとして報告します。spec/VERIFICATION.mdは Rust の bundle ビルダーの名前を 正しく記すようになりました(wasm_build_bundle、wasm機能のみ)。- Go SDK:
SignBundleV2はsigned_bundle.schema.jsonが禁じている空のsignature.signer.idのままに していたため、4 つの SDK の検証者は受け入れるのに、リファレンスの検証者、CLI、サーバーはそれが署名したすべての bundle を拒否していました(tools/interop-matrixが発見)。署名者は今では bundle の責任を負うプリンシパル (signer.id= RPR のhuman_id)で、RPR にhuman_idのない bundle は署名前に拒否されます。 -
A2A セッション(TypeScript、Python、Go):
decryptMessage/decrypt_message/DecryptMessageは、受信 ウィンドウ内で受け入れたシーケンスを保持し、順序が入れ替わっていても各シーケンスを 1 度だけ受け入れます。 負でない整数でないシーケンスは拒否し、シーケンスは認証タグを検証した後にだけ記録します。受信カウンターより ウィンドウ 1 つ分以上先にあるシーケンスは拒否します(DCP-04 §8.4)。新しいフィールドなしで復元された セッション(TypeScript のundefined、Go のnil、Python のNone、コンストラクターの既定値)は、受信 カウンターより下にあるウィンドウ内のすべてのシーケンスを受信済みとみなします。verifyResumeProof(TypeScript)は、Python と Go がすでにそうしていたように、定数時間で比較します。Go のセッションは並行利用に 対して安全でないことを文書に記しました。 -
Rust SDK:
serde_jsonにfloat_roundtripを有効にしました。その高速な浮動小数点のパーサーは長い 10 進 リテラルで 1 ULP ずれるため、9007199254740991.0(dcp-jcs-v1は他のすべての SDK と同じく整数 9007199254740991 として読む)が 9007199254740990 になり、2251799813685247.0が整数でなくなっていました。 その結果、Rust の検証者は、TypeScript、Python、Go の検証者が受け入れる署名や制限を拒否していました。共有 ベクターはlimits_written_in_decimal_formです。 @dcp-ai/wasm: npm パッケージにpkg/(.wasmバイナリとそのグルーコード)を含めるようにしました。 wasm-pack はpkg/.gitignore=*を書き出し、npm は入れ子の.gitignoreファイルに従うため、@dcp-ai/wasm@2.0.0はpkg/なしで公開され、実行時の../pkg/dcp_ai.jsのインポートが失敗していました。 ビルドはそのファイルを削除し、テストスイートが tarball を確認します。@dcp-ai/sdk: 同梱するテレメトリーのバージョンを、ビルドスクリプト内のリテラルではなく、ビルド時にpackage.jsonから読む(tsup.config.ts)ようにしました。2.2.0 は自らを 2.1.2 と報告するところでした。- Python の
verify_signed_bundle_v2は、composite_sigのない成果物をMalformed signed bundle: KeyError('composite_sig')と報告していました。今は他の SDK と同じく、エラーが 成果物を示します(intent: Missing composite signature)。 - TypeScript の
verifySignedBundleV2は、構造的に不正な形式の署名済み bundle に対して、例外を投げる代わりに 失敗の判定(Malformed signed bundle: ...)を返します。対象は、欠けている、null、またはオブジェクトでないbundle、signature、manifest、audit_entries、nullの監査エントリー、正規化するオブジェクト内の整数で ない数値(0.5、1e400)です(spec/VERIFICATION.mdV2-3、V2-5)。Python、Go、Rust の検証者はすでにこれらを 拒否していました。tools/difffuzzが発見しました。 - Go の V1 の
VerifyObjectは、デコードして 32 バイトにならない公開鍵でパニックしていました(ed25519.Verifyはそれ以外の長さでパニックする)。今はデコード後の長さを確認し、代わりにエラーを返します。VerifySignedBundleはその周りの動作を保ちます。公開鍵が空なら署名に埋め込まれた鍵を使い、両方ともなければmissing public keyになり、VerifyObjectのエラーはSIGNATURE INVALIDとして報告します。 - TypeScript の CBOR デコーダー(
sdks/typescript/src/wire/cbor.ts、省略可能)は、重複したマップのキー、不正な UTF-8、安全な整数の範囲外の整数と長さを拒否します。U+FEFF はテキストのデータとして保持し、__proto__の キーはセッターを呼び出すのではなく自身のプロパティとして定義し、エンコーダーは孤立したサロゲートを置き換える のではなく拒否します。これはデコーダーの入力処理を強化するもので、完全な正規 CBOR デコーダーではなく、正規化 プロファイルを追加するものでもありません。
ドキュメント¶
spec/profiles/admission/README.md(アドミッションのプロファイル):編集上の明確化です。ベクトル、スキーマ、SDK の動作は変わらず、 4 つの SDK はすでにここに書かれたとおりに動作します。§5.1 の手順 2 はバンドルを V2 の署名付きバンドルとして検証します。 V2 でないバンドルはallow_v1_bundlesが何であっても検証を通らず、プロファイルのもとでは P1 が検証の前に止まり、 バンドルを検証を通らなかったものとして報告します。プロファイルには信頼セットが必要です。組み合わせた関数と単独の手順 3 は、 信頼セットのないプロファイルをCONFIG_PROFILE_CONTRADICTIONで拒否し、組み合わせた関数は、プロファイルと呼び出し元の 検証器のポリシーが一緒に与えられた場合も同じコードで拒否します。それが検証の前か後かは定めません。§4.1 では、4 つのモードの 列挙の外にあるモードは型の誤った値と同じくCONFIG_INVALID_VALUE、その列挙のうちhybrid_required以外のモードや、 許された部分集合の外にあるアルゴリズムはCONFIG_PROFILE_CONTRADICTIONです。§2.2:信頼セットに複数の問題がある場合は、 そのどれか 1 つのコードを報告してかまいません。どれを報告しても拒否され、優先順位は定めません。§5.2:errorsは §5.1 の 段階の順に従い、確認は構成要素や対象ごとに 1 回ずつコードを加えてかまわず、1 つの段階の中では順序を定めません。tools/conformance/README.md:証拠カタログが判定するerror_containsの文字列(241 ケースのうち 146 ケース)は SDK の診断用の文言であり、規範ではありません。docs/QUICKSTART_CREWAI.md: どちらの例も動いていませんでした。V1 の例は Python SDK にないbuild_bundleを インポートし、intent_hashとprev_hashにハッシュを入れるべきところに署名を書いていました。V2 の例は一度も 公開されていない API を使い、dcp_ai.v2が(2.9.0 から)同梱しているにもかかわらず、Python SDK には V2 の bundle のビルダー、署名者、検証者がないと書いていました。今は両方とも SDK を実際のとおりに使います。ツールの 実行前にポリシーのゲートが判断し、検索クエリは記録に含めず、ツール呼び出しごとに専用の bundle を封印し、検証で オペレーターを固定します(V1 ではその公開鍵、V2 ではhybrid_requiredのもとでその RPR のハッシュと kid、 そして各 kid がその鍵から導出されていること。bundle 自身の鍵では bundle が自己整合していることしか分からない ため)。bundle は Python とdcp verify-bundleで、V2 のものはさらに TypeScript、Go、Rust の SDK でも検証 できます。ガイドは CrewAI のドキュメントどおりcrewai.toolsからtoolをインポートし、npm create @dcp-ai/crewaiのひな形を、実際そうであるようにプレースホルダーを使った手順として説明します。integrations/crewai/README.md: 例は、スキーマが拒否する値(liability_mode: "full"、能力write_file)を 持つ V1 のペイロードを使い、監査エントリーにはないaction_typeフィールドを出力していました。今は動作します。 README には、DCPCrewAgentとDCPCrewが署名のない記録を保持し、CrewAI を実行しないことを記し、session_nonceのパラメーターを列挙しました。- 英語と、es、zh-CN、ja、pt-BR の翻訳のドキュメントを最新にしました。すべての SDK の README における委任 チェーン、A2A の受信ウィンドウ、Testing & Assurance(相互運用性マトリクス、差分ファザー、共有ベクター)、 訂正した事実(Go 1.25、Rust の FIPS クレート、スキーマ外のフィールドを使っていた TypeScript の DCP-09 の例)、 翻訳に欠けていた README の行です。
docs/EU_AI_ACT_MAPPING.md: 規則(EU)2026/1744 で改正された規則(EU)2024/1689(EU AI 法)のロギング、人間に よる監督、記録の保持、説明、インシデントの証拠に関する義務を、DCP-AI の成果物がどう支えるか。適用の スケジュール、実装者向けのチェックリスト、DCP が扱わない空白を含みます。条文は 2026 年 10 月 22 日に EUR-Lex で 確認しました。spec/DCP-09.md§3.5 は、実際のワイヤー上のフィールドに基づいて再委任を規定し、チェーンの検証について規範的な 規則を定めるようになりました。§2、§10.3、§10.6 はDCP-AI.v2.SubMandateコンテキストを列挙します。spec/DCP-AI-v2.0.md§4.1 はコンテキストタグDCP-AI.v2.DelegationとDCP-AI.v2.SubMandateを列挙し、 §14.2 は、委任チェーンの実効的な階層が階層を引き上げることしかできない入力であると述べています。
[2.10.0] - 2026-10-22¶
パッケージのバージョン¶
dcp-ai(PyPI)2.8.2 → 2.9.0: pqcrypto 1.x、FIPS 205 の SLH-DSA、ML-KEM-768、V2 の bundle と V2 の 検証者。blind_rpr(pii_saltが必要)とpqcrypto<1.0のインストールについては互換性のない変更です。@dcp-ai/sdk(npm)2.1.2 → 2.2.0:verifySignedBundleV2のセキュリティ修正、セキュリティ階層の強制、 ブラインド化された RPR のエクスポート。blindRpr(pii_saltが必要)については互換性のない変更です。github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2v2.9.0 → v2.10.0: V2 の検証者の強化と階層の強制。BundleBuildInput(署名済みの成果物)とBlindRPRについては互換性のない変更です。dcp-ai(crates.io)2.9.0 → 2.10.0: ネイティブの V2 検証者、階層の強制、RFC 3339 による有効期限の解析。blind_rprとwasmの bundle ビルダーについては互換性のない変更です。@dcp-ai/wasm2.0.0 → 2.1.0:buildBundleは署名済みの成果物を受け取り、verifyBundleは完全な検証者 ポリシーを受け取ります。@dcp-ai/openclaw2.0.0 → 2.1.0: セキュリティ階層の下限と、署名済みの RPR のpii_salt。- 変更なし:
@dcp-ai/cli2.0.0 とその他のインテグレーションのパッケージ。
セキュリティ¶
- ブラインド化された RPR のコミットメントに、4 つの SDK すべてでソルトを付けました。
pii_hashはsha256(canonical({ contact, legal_name }))だったため、プリンシパルの名前と連絡先を推測した者は誰でも、 公開済みのブラインド化された RPR でその推測を確認でき、不変のログやアンカー上ではそれが永遠に変わりません でした。完全な RPR は今ではpii_salt(CSPRNG による 32 バイト、小文字の 16 進)を持ち、これは RPR とともに 署名され、決して公開されません。pii_hashはsha256(canonical({ contact, legal_name, pii_salt }))です。完全な RPR を、それとともにソルトを削除すると、 公開されたコミットメントは開けなくなります(spec/DCP-AI-v2.0.md§12.1)。contactやlegal_nameがない 場合は、すべての SDK でnullとしてハッシュされます。TypeScript は以前はキーを省いていました。tests/interop/v2/interop_vectors.jsonの新しいカテゴリーblinded_rpr(ソルト付きと従来のpii_hash、期待 されるブラインド化された記録)は 4 つの SDK のテストスイートすべてで実行され、generate-interop-vectors.tsがこれを出力します。 - ブラインド化された RPR の検証(
verifyBlindedRpr、verify_blinded_rpr、VerifyBlindedRPR)は、4 つの SDK すべてでsession_nonceとbinding_keysも比較するようになりました。以前は、バインディング鍵やセッション nonce が異なる完全な RPR でも、ブラインド化された記録と一致していました。Go では、JSON からデコードした リストのフィールドが、[]stringとして作った同じリストと一致しないことはなくなりました。 - 検証サーバー:
POST /v2/passport/registerはパスポートの複合自己署名を検証し、その署名者の鍵だけを 登録します。agent_idを再登録するには、そのすべての有効な鍵で署名された、より新しいパスポートが必要です。 以前は誰でも、自分の鍵でエージェントを再登録し、自分の緊急トークンを仕込んで、緊急失効させることができました。POST /v2/keys/rotateは所持証明と古い鍵による認可(verifyKeyRotation)を検証し、POST /v2/multi-party/authorizeは各当事者の署名を登録済みの鍵で検証し、各当事者を 1 回だけ数えます。 - 検証サーバー:
/v2/policy/mode、/v2/governance/register、/v2/advisory/publish、/v2/advisory/auto-applyはAuthorization: Bearer $OPERATOR_TOKENを必要とします(未設定の場合はロック)。 勧告はスキーマで検証され、上限は 1000 件です。レート制限は、クライアントが提供するX-Forwarded-Forではなく ソケットのアドレスをキーとし(プロキシの背後ではTRUST_PROXY=true)、VERIFIER_MODE/ALLOW_V1_BUNDLESは環境から読みます。allow_v1_bundlesが適用されるようになりました。 - 失効サービス: エージェントは署名済みのパスポートで登録し(
POST /v2/register)、kid の所有、鍵の有効期限、 緊急トークンが記録されます。再登録には、エージェントの有効な古典と PQ の鍵で署名された、より新しい パスポートが必要で、/revokeと/v2/revokeはその有効な鍵で署名されていなければなりません。GET /v2/check/kid/:kidは、?agent_id=なしで、登録済みの kid の緊急失効を報告します。 - アンカーサービス: ランダムな
tx_hashはなくなり(記録はtx_hash: null、onchain: falseを持つ)、本文は 1 MB に制限され、POST /flushにはオペレーターのトークンが必要で、不正な形式の入力はクラッシュではなく 400 に なります。透明性ログ: ツリーヘッドは、他の誰も検証できない HMAC ではなく Ed25519 で署名されます。OPERATOR_KEYは 16 進 64 文字のシードでなければならず(compose の公開されたプレースホルダーは削除)、 Merkle 木は RFC 6962 の葉とノードのプレフィックスを使い、POST /gossip/peers(SSRF の経路)にはオペレーターの トークンが必要です。 - 検証サーバーと失効サービス: 期限切れの鍵は、パスポートの再登録、鍵のローテーションの認可、当事者や失効の
ための署名ができなくなりました。また、再登録では登録済みの鍵のエントリーを保持するため、新しいパスポートで
鍵の
expires_atを延ばすことはできません。 - Fly の設定は、検証と失効のマシンをそれぞれ 1 台ずつ稼働させたままにします。ゼロまでスケールすると、マシンが アイドルになるたびにメモリー上のレジストリが消えていました。
- TypeScript SDK:
verifySignedBundleV2はspec/VERIFICATION.mdのステップ V2-7 と V2-8 を実装します。 存在する PQ 署名(pq_over_classical)は、どのモードでも検証に成功しなければなりません。hybrid_preferred(中リスクの既定値)は不正な PQ 署名を警告付きで受け入れ、classical_onlyはそれを無視して いました。許容されるのは PQ 署名がない場合(classical_onlyのバインディング)だけで、hybrid_requiredとpq_onlyでは許容されません。各成果物自身のcomposite_sigも、同じ規則とそのコンテキストタグで検証される ようになりました。RPR はそのbinding_keysで、パスポート、意図、ポリシー決定はパスポートのkeysで検証 します。以前はpayload_hashしか確認しなかったため、意図に対するエージェントの偽造署名がhybrid_requiredのもとでも検証に成功していました。リファレンスの検証者、dcp verify-bundle、サーバーは、次の@dcp-ai/sdkのリリースでこれを受け取ります。 - TypeScript SDK:
verifySignedBundleV2は認識できない検証モードに対してフェイルクローズし、モードがclassical_only、hybrid_preferred、hybrid_required、pq_onlyのいずれでもない検証者ポリシーを拒否します。 - Go(
v2.VerifySignedBundleV2)と Rust の SDK: 各成果物のcomposite_sigを同じように検証し(V2-8)、 署名者の鍵をkidで探します(V2-6)。bundle の署名者はパスポートのkeysと RPR のbinding_keysから 探します。以前はパスポートの Ed25519 と ML-DSA-65 の鍵をアルゴリズムで選んでいたため、プリンシパルの鍵で 署名された bundle を拒否し、パスポートに Ed25519 の鍵が 1 つもない bundle を、署名を確認しないまま、警告付きで 検証済みと報告していました。 - TypeScript、Go、Rust の SDK: すべての複合署名で、すべての検証モードにおいて、古典の枠には Ed25519、PQ の枠には
ML-DSA-65 または SLH-DSA-192f が入り、その鍵の
algが同じでなければなりません。Go はさらに、RPR、 パスポート、意図、ポリシー決定が null またはオブジェクトでない bundle を拒否します(以前はその成果物の確認を すべて飛ばしていました)。TypeScript は、そのような bundle に対して例外を投げる代わりにverified: falseを 返します。 - セキュリティ階層(仕様 §14.2): Go SDK と
@dcp-ai/wasmのバインディング(wasm_compute_security_tier)は、 意図のスキーマが許さないpayment/transfer、financial、health、legal、biometricで照合していたため、 スキーマ上有効なinitiate_payment、financial_data、health_dataの意図が、そこではroutine、 TypeScript、Python、Rust の SDK ではelevatedになっていました。今は 4 つの SDK とバインディングが同じ階層を 計算し、tests/interop/v2/interop_vectors.jsonの新しいsecurity_tierベクターで確認します。 - 検証サーバー:
POST /verifyとPOST /v2/bundle/verifyのresolved_tier、および/v2/bundle/verifyの 階層の確認は、intent.security_tierをそのまま使っていたため、routineと宣言したエージェントは自らの階層を 下げることができ、さらにスキーマが許さないのに意図からrisk_scoreを読んでいました。今は §14.2 の規則 (lib/security-tier.js)を使います。risk_scoreは bundle のポリシー決定から読み、estimated_impactを 使い、未知の値はelevatedとし、明示的な階層は結果を引き上げることしかできません。/v2/intent/declareも 同じ方法でresolved_tierを計算します。 - OpenClaw のインテグレーション:
dcp_verify_bundleとdcp_log_actionはintent.security_tierをそのまま 使っていたため(security_tier ?? computeSecurityTier(intent))、宣言された階層が計算された階層を下げることが でき、ポリシー決定も渡していませんでした。今は明示的な階層は階層を引き上げることしかできません。ポリシー決定も 渡すため、@dcp-ai/sdkがそれを読むようになれば(2.1.2 の次のリリース)risk_scoreが考慮されます。 - リファレンスのサービスに対するサービス拒否(その状態はメモリー上にあり、再起動を越えて残りません):
- 検証サーバー: 登録はクライアントごとにレート制限され(
REGISTRATIONS_PER_HOUR、既定値は 1 時間あたり 20)、ローテーションではエージェントの直近 4 つの退役した鍵だけを保持し、登録されたパスポートからはcreated_atだけを保存します。ローテーションを繰り返す 1 つのエージェントや大量の登録によって 10,000 個の 鍵のレジストリが埋まり(再起動まで 507)、保存される署名済みパスポートはそれぞれ最大 1 MB を占めることが ありました。捨てられた鍵は墓標として失効したまま残り、二度と登録できません。エージェントが生涯に登録できる 鍵は最大MAX_KEYS_PER_AGENT個(64)です。ローテーションは上限の確認の前に退役した鍵を捨てるため、満杯の レジストリにも収まります。再登録時の鍵ファミリーの確認で、レジストリを 2 乗のオーダーで走査し直すことは なくなりました。 - 透明性ログ:
POST /gossip/exchangeは、固定されたピアが署名した正しい形式のツリーヘッドを、16 KB 以下の 本文でだけ受け入れ、直近の 100 件の異なるアラートを保持します。そのため、リプレイされたツリーヘッドが古い アラートを押し出すことはできません。ポーリングで得たツリーヘッドはピアの固定された鍵で検証できなければ ならず、1 回のポーリングで読むのは最大 16 KB で、1 間隔でタイムアウトし、前のポーリングと重なることは ありません。以前は、誰でもアラートのリストを 1 MB の文字列で埋めることができ、ピアのツリーヘッドは一度も 検証されず、応答しないピアに対してはポーリングが積み重なっていました。 - 失効サービス:
POST /v2/registerはクライアントごとにレート制限され、上限はMAX_AGENTS(既定値 10,000) で、保存するフィールドも制限されます。そのため、大量の登録や大きすぎる記録によってメモリーを使い果たし、 すべての失効を消してしまうことはなくなりました。 - 検証サーバーと失効サービス: 新しい
agent_idの登録にはオペレーターのトークンが必要です。パスポートは 自己署名されているだけなので、誰でも被害者のagent_idを先に自分の鍵とトークンで登録し、その後で緊急失効 させたり、409 で本物のエージェントを締め出したりできました。再起動のたびに、すべてのagent_idがこの状態に 戻っていました。GET /v2/check/kid/:kidは、一度も登録していない kid に対して、呼び出し側が?agent_id=で 指定したエージェントの判定ではなく、404(registered: false)を返します。 - 検証サーバーと失効サービス: 公開鍵と署名は、ちょうどそのアルゴリズムのサイズの正規の base64 でなければ
ならず、V2 のスキーマは
public_key_b64とsig_b64を base64 のアルファベットに限定し、長さを制限します。 寛容なデコーダーは空白を読み飛ばしていたため、900 KB の空白を詰めた ML-DSA の鍵が登録されてそのまま返され、 空白を詰めた署名が保存されて/v2/listで公開されていました。 - TypeScript SDK の
verifySignedBundleV2はセキュリティ階層を強制します(仕様 §14.3)。ポリシーのモードと、 署名済みの意図とポリシー決定から計算した階層のモードのうち厳しい方で検証し、それをdetails.resolved_tierで報告します。以前は、モードはエージェント自身のpassport.risk_tierだけから決まっていたため、DEFAULT_VERIFIER_POLICYのもとでは、risk_tier: "low"と宣言したパスポートは、支払いの意図であってもclassical_onlyになっていました。 - TypeScript SDK:
AdaptiveRateLimiter.check、generateSessionExpiry、VerificationCache.setは、未知の 階層名やconstructorのようなプロトタイプのキーをelevatedとみなします。以前は、レートリミッターは でっち上げの名前ごとに別のバケットを作り、generateSessionExpiryはconstructorで例外を投げ、キャッシュは そうしたエントリーを期限切れにしませんでした。 - OpenClaw のインテグレーション:
dcp_declare_intentは、意図とポリシー決定に署名して入れる階層を、意図の スコアを付ける前に計算していました。今はリスクスコアを渡し、@dcp-ai/sdkがそれを読むようになれば(2.1.2 の 次のリリース)考慮されます。 - Go(
v2.VerifySignedBundleV2)、Rust(v2::verify_bundle::verify_signed_bundle_v2と、@dcp-ai/wasmのverifyBundleの裏にあるバインディングwasm_verify_signed_bundle_v2)、Python(verify_signed_bundle_v2) の検証者は、TypeScript のものと同じくセキュリティ階層を強制します。モードはポリシーのモードと階層のモードの うち厳しい方で、bundle の署名と各成果物の署名に適用されます。未知のポリシーのモードはフェイルクローズし、結果は 階層とモードを報告します。Go と Rust の検証者には検証者ポリシーがなく、どの意図に対してもclassical_onlyの 署名を受け入れていました。 - Python SDK の
verify_signed_bundle_v2: TypeScript、Go、Rust の SDK と同じく、すべての複合署名で、すべての モードにおいて、古典の枠には Ed25519、PQ の枠には ML-DSA-65 または SLH-DSA-192f が入り、その鍵のalgが 同じでなければなりません。以前はpq_onlyのもとで、古典の枠の ML-DSA-65 を受け入れていました。 - Go と Rust の SDK: 複合署名は
pqメンバーを持たなければならず、classical_onlyの場合はnullです (schemas/v2/composite_signature.schema.json)。以前は、pqがない場合をnullと同じようにデコードし、 TypeScript と Python の検証者が拒否するそのようなclassical_onlyの署名を検証に通していました。bundle_vectors.jsonがclassical_only_bundle_signature_without_pqでこれを固定します。 - Go と Rust の V2 検証者は、TypeScript と Python のものと同じく、監査証跡を署名済みのマニフェストに結び付け
ます。
audit_merkle_rootを再計算し、audit_countを確認し、チェーンがGENESISから始まることを求めます。 以前は、正しく署名された bundle の監査エントリーを、でっち上げた自己整合的なチェーンに置き換えても、両方とも 検証済みと報告していました。 - Go と Rust の V2 検証者は、マニフェストの確認を実行できない場合にフェイルクローズします。
rpr_hashのような 成果物のハッシュがない場合や、ペイロードがない、または正規化できない場合は、確認を飛ばすのではなくエラーに なります。 - Go と Rust の V2 検証者は、TypeScript と Python のものと同じく、各成果物の
payload_hashをそのペイロードと 照合します。以前は無視していました。 - Go と Rust の V2 検証者は、
manifest.session_expires_atを過ぎた bundle を拒否するため、期限切れの セッションをそれらに対してリプレイすることはできなくなりました。SystemTime::now()はwasm32-unknown-unknownでパニックするため、@dcp-ai/wasmの検証者は JavaScript から時計を読みます。 - Rust SDK:
is_session_expiredは RFC 3339 の文字列を UTC の時計と辞書順で比較していたため、オフセット付きの タイムスタンプを最大 14 時間誤って判断していました。-05:00で書かれた 1 時間後に終わるセッションは期限切れと され、+05:00で書かれた 1 時間前に終わったセッションはまだ有効とされていました。今はタイムスタンプを解析し (parse_rfc3339_millis)、時点を比較します。セッションと鍵の有効期限、勧告のヘルパーで適用します。 - 4 つの検証者すべてにおける有効期限のタイムスタンプ: 存在するのに
Zまたは±hh:mmのオフセットを持つ RFC 3339 のタイムスタンプでないsession_expires_atや鍵のexpires_atは拒否されます。存在しない場合やnullは、引き続き有効期限なしを意味します。TypeScript は、Dateが解析できないもの("n/a")や寛容に解析 するもの("2099-12-31")を何でも受け入れ、空のsession_expires_atを飛ばしていました。Rust は"n/a"を 受け入れ、Go は文字列でない鍵のexpires_atを飛ばし、Python は例外を投げていました。isSessionExpiredとis_session_expiredは、不正な形式の値を期限切れとみなします。 - 鍵の有効性の確認は、署名できるすべての鍵を対象とします。4 つの検証者すべてが、RPR に署名し、bundle にも
署名しうる、プリンシパルの RPR の
binding_keysにある失効または期限切れの鍵を拒否します。TypeScript と Python はパスポートの鍵しか確認していませんでした。Go と Rust の検証者は鍵の状態をまったく確認しておらず、 今はパスポートの失効または期限切れの鍵も拒否します。 - 4 つの検証者すべてが、
revokedと同じく、statusがexpiredの鍵を拒否します。鍵エントリーのスキーマはexpiredを許していますが、確認していたのはrevokedだけだったため、expires_atのない期限切れと印を 付けた鍵が署名を続けていました。 - 空の監査証跡は、
sha256:の後に 64 個のゼロが続く Merkle ルートを持たなければなりません。Go と Rust の ビルダーはすでにそう書いていました。4 つの検証者すべてが、bundle に監査エントリーがないときにaudit_merkle_rootを飛ばしていたため、そこにはどんな値でも入れることができました。
変更(互換性のない変更)¶
- 検証サーバー(
POST /v2/passport/register)と失効サービス(POST /v2/register): 新しいagent_idにはAuthorization: Bearer $OPERATOR_TOKENが必要です(なければ 401)。再登録は引き続きセルフサービスです。 失効サービスのGET /v2/check/kid/:kidは?agent_id=を無視し、登録されていない kid には 404 を返します。 - 検証サーバー: エージェントが生涯に登録できる鍵は最大
MAX_KEYS_PER_AGENT個(既定値 64)です。それ以降の ローテーションは 409 になり、エージェントは新しいagent_idを登録する必要があります。 - スキーマ:
key_entry.public_key_b64とcomposite_signatureのsig_b64は^[A-Za-z0-9+/]+={0,2}$に 一致しなければならず、長さはそれぞれ 3,456 文字と 66,476 文字までです。 - 透明性ログ:
GOSSIP_PEERSの各エントリーは<url>#<base64 Ed25519 public key>です。鍵が固定されていない ピアのツリーヘッドは無視され、/gossip/exchangeはそれらを拒否します(403)。Docker Compose のログは、鍵が 設定されて初めてゴシップします(docker/README.mdを参照)。 - Go SDK:
BundleBuildInputは署名済みの成果物(SignedPayload、v2.SignPayloadを参照)と[]AuditEventV2の監査エントリーを受け取ります。BuildBundleV2は署名のないペイロードを包んでおり(検証者は 今ではこれを拒否します、V2-8)、bundle を空の監査エントリーで埋めていました。 - WASM(
wasm_build_bundle、および@dcp-ai/wasmのbuildBundle): 各成果物は、生のペイロードではなく、wasm_sign_payload/signPayloadによるSignedPayloadです。生のペイロードから作った bundle は成果物の 署名を持たず、もう検証に成功しません。 - 失効サービス:
POST /v2/register-emergency-tokenとPOST /v2/register-key-expiryを削除し、POST /v2/registerに一本化しました。V1 の/revokeにはそこに登録されたエージェントが必要で、登録には ハイブリッド(Ed25519 + ML-DSA-65 または SLH-DSA-192f)のパスポートの署名が必要なため、Ed25519 のみの(V1 の) エージェントは失効を公開できなくなりました。失効したエージェントを再び失効させることはできません(409)。 - 検証サーバーと失効サービス:
agent_idの再登録(たとえば緊急失効トークンを置き換えるため)には、登録済みの ものよりcreated_atが新しく、エージェントのすべての有効な鍵で署名されたパスポートが必要です。トークンのない パスポートは登録済みのトークンを保ちます。ある系統(古典または PQ)の有効な鍵をすべて失ったエージェントは 再登録できません。回復は緊急失効トークンかオペレーターを通じて行います。 - 透明性ログ: RFC 6962 のプレフィックスにより、葉のハッシュ、ルート、包含証明が変わり、STH の
signature/public_keyは base64 の Ed25519 になりました。/addはsha256:<64 hex>のハッシュだけを、アンカーの/anchorは省略可能なsha256:プレフィックス付きの 16 進 64 文字だけを受け付けます。 - 検証サーバー:
/v2/keys/rotateはauthorization_sigとtimestampを必要とします(KeyRotationRecord)。dcp rotate-keyとdcp keys certifyはまだシミュレーションの所持証明を送っており、サーバーは今ではそれを 拒否します。 - Python SDK: SLH-DSA-192f は、TypeScript、Go、Rust の SDK と同じく、FIPS 205(純粋な SLH-DSA、空の
コンテキスト)を実装するようになりました。以前は PQClean の標準化前の SPHINCS+ に基づいており、
0x00 || 0x00 || messageではなくメッセージそのものに署名していたため、SLH-DSA の署名はどちらの方向でも SDK 間で 検証できませんでした。dcp-ai2.8.2 以前のSlhDsa192fProviderが作った署名は、もう検証に成功しません。 - Python SDK: 2.8.2 の
<1.0の上限ではなくpqcrypto>=1.0,<2を必要とし、それを ML-DSA-65、SLH-DSA-192f、 ML-KEM-768 に使います(pqcrypto1.0 は API を変更し、SPHINCS+ を削除しました)。dcp_ai.providersはImportErrorを握りつぶさなくなり、PQ の相互運用性テストはプロバイダーがない場合でもスキップされなくなりました。 - Python SDK:
VerifierPolicyは未知のフィールドを捨てるのではなく拒否し、欠けていたフィールド (allow_classical_fallback_disable、warn_classical_only_deprecated、advisory_rejected_algs、require_session_expiry、max_session_duration_seconds、require_audience_binding、verifier_id)を 追加しました。以前はVerifierPolicy(require_audience_binding=True, verifier_id=...)が両方のフィールドを黙って失っていました。verify_signed_bundle_v2では、dict のポリシーはVerifierPolicyとして検証され(未知のキーは例外を投げる)、省かれたフィールドには、既定のポリシーのlow→classical_onlyではなく、モデルの既定値(すべてのリスク階層でhybrid_required)が使われます。default_modeがすべての階層に適用されるのはrisk_overrides=Noneの場合だけです。 - 4 つの SDK すべてで、ブラインド化には
pii_saltが必要です。完全な RPR にpii_saltがない、またはそれが小文字の 16 進 64 文字でない場合、blindRpr(TypeScript)とblind_rpr(Python、ValueError)は例外を投げ、BlindRPR(Go)とblind_rpr(Rust)はエラーを返します。RPR に署名する前に新しいヘルパーで設定してください。 ソルトなしで署名された RPR は、ブラインド化する前に署名し直す必要があります。 - 4 つの SDK すべてで、ブラインド化された RPR の検証は、
pii_saltがあるのに小文字の 16 進 64 文字の文字列でない 完全な RPR を拒否します。以前は、別の場所で空または短いソルトでブラインド化された記録が警告なしで検証に成功し、 一方でソルトのない記録には印が付けられていました。 - ブラインド化された RPR の検証結果:
verify_blinded_rpr(Python)は新しいキーwarningsを返し、Go のBlindedRprCheckには新しいフィールドWarningsがあります。そのため、結果全体を比較するコードや、 フィールド名のないリテラルでBlindedRprCheckを作るコードは変更が必要です。 schemas/v2/responsible_principal_record.schema.jsonはpii_saltを受け付けます。スキーマはadditionalProperties: falseなので、以前のスキーマで検証する検証者はソルトを持つ RPR を拒否します。生成側が それを設定し始める前に、検証者を更新してください。- Rust SDK:
ResponsiblePrincipalRecordV2に新しい公開フィールドpii_salt: Option<String>があるため、構造体 リテラルではそれを設定する必要があります。 - セキュリティ階層の計算(仕様 §14.2)、すべての SDK:
risk_scoreは bundle のポリシー決定から読み、意図からは 決して読みません(意図のスキーマはそれを許さないため、有効な意図で階層がstandardになることはありません でした)。estimated_impactがmediumなら階層をstandardに、highならelevatedに引き上げます。action_type、estimated_impact、data_classesの値が欠けている、型が誤っている、または未知の場合は、少なくともelevatedになります。明示的なintent.security_tierは結果を引き上げることしかできません。 - TypeScript:
computeSecurityTier(intent, policyDecision?)。 - Python:
compute_security_tier(intent, policy_decision=None)。compute_security_tier({})は今ではelevatedです。LangChain と CrewAI のインテグレーションは、独自のコピーの代わりにこれを使います。 - Go:
SecurityTierInputにEstimatedImpactとSecurityTierを追加し、そのゼロ値(または nil のDataClasses)は今ではelevatedです。v2.SecurityTierInputFromPayloads(intent, policyDecision)は、 デコードしたペイロードから入力を作ります。 - Rust:
compute_security_tier(intent, policy_decision: Option<&Value>)。wasm_compute_security_tierと@dcp-ai/wasmのcomputeSecurityTierは省略可能なポリシー決定を受け取ります。 - セキュリティ階層の計算、すべての SDK とリファレンスサーバー: ポリシー決定の
risk_scoreが欠けている、または 0 から 1000 の整数でない場合は、意図の未知の値と同じく未知とみなされ、階層は少なくともelevatedになります。 以前は、数値でない値は 0 とみなされ、それ以外の数値はそのまま比較されていたため、-1はroutineに、1e30はmaximumになっていました(今はelevatedで、モードは同じhybrid_required)。ポリシー決定がない場合、 スコアは引き続き 0 です。Go では、SecurityTierInputFromPayloadsはそのような値に対してRiskScoreを -1 に 設定し、ComputeSecurityTierは 0..1000 の範囲外のRiskScoreをすべて未知として扱います。 - TypeScript SDK の
verifySignedBundleV2: 今はclassical_onlyの署名で合格している bundle も、意図が機微な 場合は拒否されます。対象は、initiate_payment、pii、financial_data、health_data、credentials、children_data、estimated_impact: "high"、ポリシー決定のrisk_scoreが 500 以上、または意図のスキーマ外の 値です。それらにはハイブリッド(pq_over_classical)の署名をしてください。ルートの検証者 (lib/verify.js、dcp verify-bundle、サーバー)は、次の@dcp-ai/sdkのリリースでこれを受け取ります。 - Go、Rust、Python の検証者は、同じ
classical_onlyの bundle を拒否します。Go のVerifySignedBundleV2と Rust のverify_signed_bundle_v2は、ポリシーなしの代わりに TypeScript のDEFAULT_VERIFIER_POLICYを適用 します。wasm_verify_signed_bundle_v2は省略可能なポリシーの JSON(VerifierPolicy)を受け取り、それがある 場合は V1 の bundle を拒否します。そのポリシーが既定値と異なってよいのは、default_mode、risk_overrides、 フェーズ 3 のフィールド(advisory_rejected_algs、warn_classical_only_deprecated、allow_classical_fallback_disable。TypeScript と同じく適用)だけです。それ以外の変更や、Rust のVerifierPolicyの JSON にある未知のフィールドは、無視されるのではなく検証を失敗させます。 - Python SDK の
verify_signed_bundle_v2: TypeScript と同じく、bundle の署名に関するエラーと警告はbundle:で始まり、null またはオブジェクトでない成果物は<name>: not a SignedPayload objectと報告され、未知の ポリシーのモードは、どの署名を確認するよりも前にUnknown verification mode in verifier policyで失敗します。
追加¶
generatePiiSalt(TypeScript)、generate_pii_salt(Python、Rust)、GeneratePIISalt(Go)。4 つの SDK すべての RPR の型、schemas/v2/responsible_principal_record.schema.json、api/proto/dcp.protoがpii_saltを持ちます。スキーマに null がないため、Python のResponsiblePrincipalRecordV2は、設定されて いないpii_saltをシリアライズ時に省きます。- ソルトのない従来のブラインド化された RPR も、非推奨の警告付きで引き続き検証に成功します。
verifyBlindedRpr(TypeScript)、verify_blinded_rpr(Python)、VerifyBlindedRPR(Go)の結果はwarningsのリストを持ちます。新しい公開フィールドはそれを作ったり分解したりする呼び出し側を壊すため、Rust のBlindedRprCheckは 2 つのフィールドを保ちます。そこでは、完全な RPR にpii_saltがない、または null である ことで、従来の記録であることが分かります。 @dcp-ai/openclaw:dcp_identity_setupは RPR にpii_saltを付けて署名するため、記録は後で署名し直さずに ブラインド化できます。- 失効サービス:
REVOCATION_STATE_PATHは登録と失効をファイルに保持します(既定はメモリーのみ)。書き込みは fsync した JSON の行として追記され、起動時にファイルを再生し、アトミックな名前の変更でコンパクションします。パスに書き込め ない場合やファイルが 512 MB を超える場合、サービスは起動を拒否します。Docker Compose のスタックはこれをボリューム 上に設定します。 - 検証サーバー:
MAX_REGISTERED_KEYSとMAX_KEYS_PER_AGENTが鍵のレジストリの大きさを決めます。 effectiveVerificationMode(TS)、effective_verification_mode(Python、Rust)、EffectiveVerificationMode(Go): ポリシーのモードと階層のモードのうち厳しい方で、pq_onlyは変わりません (仕様 §14.3)。共有ベクターはsecurity_tier.effective_modeにあります。- Go SDK:
v2.VerifySignedBundleV2WithPolicy(registry, json, policy)とv2.DefaultVerifierPolicy()。 Rust SDK:verify_signed_bundle_v2_with_policyとimpl Default for VerifierPolicy(TypeScript の既定の ポリシー)。Go と Rust のVerifierPolicyにschemas/v2/verifier_policy.schema.jsonのフェーズ 3 の フィールドを追加したため、TypeScript のDEFAULT_VERIFIER_POLICYをそのままデコードできます。@dcp-ai/wasm:verifyBundle(signedBundle, policy?)とVerifierPolicy型。Python の結果のdetailsにresolved_tierを追加しました。 tests/interop/v2/bundle_vectors.json:must_reject_bundles。低リスクのパスポートからの機微な意図を持つ 古典のみの bundle で、すべての検証者がすべてのモードで拒否しなければならないものと、モードごとの期待される判定を 持つ古典のみの routine の対照です。TS、Go、Rust、Python のテストがこれらを実行し、Python は今ではファイル全体を 実行します。default_verifier_policyは TypeScript のDEFAULT_VERIFIER_POLICYを持ち、すべての SDK がこれを ポリシーとして受け入れなければなりません。tests/interop/v2/bundle_vectors.json: 誤ったpayload_hash、置き換えられた、または切り詰められた監査 エントリー、GENESISから始まらない監査チェーン、rpr_hashのないマニフェスト、期限切れのセッション、失効 または期限切れのパスポートの鍵とバインディング鍵に対する拒否のケース。@dcp-ai/wasm:npm testは、ビルドしたパッケージのverifyBundleを Node でtests/interop/v2/bundle_vectors.jsonに対して実行し、CI がこれを実行します。以前は型チェックしか行わず、Rust の wasm32 のテストはコンパイルされるだけだったため、wasm の検証者は CI で一度も実行されていませんでした。tests/interop/v2/interop_vectors.jsonのrfc3339: オフセットや小数部を持つ RFC 3339 のタイムスタンプが 表す時点と、すべての検証者が拒否する不正な形式の値です。bundle_vectors.jsonには、不正な形式やオフセット付きの 有効期限を追加し、その署名済み bundle はオフセット付きで書いた遠い将来の有効期限を持ちます。TypeScript のparseRfc3339、Python のparse_rfc3339、Rust のparse_rfc3339_millisが検証者の使うパーサーです。- TypeScript SDK:
blindRpr、verifyBlindedRpr、isBlindedRpr、computePiiHashをパッケージのエントリー ポイントからエクスポートしました。実装されていたものの、@dcp-ai/sdk2.1.2 以前からは到達できませんでした。 Python、Go、Rust はすでにエクスポートしていました。 lib/verify.jsはverifyCompositeSig(導出した kid で署名者の鍵を探す、ペイロードに対する複合署名)とそのv2Registryをエクスポートします。lib/http.jsには、server/とservices/が共有する本文の解析、 クライアントの IP、オペレーターのトークンのヘルパーがあります。アンカーと透明性ログのサービスにはnode:testのテストスイートがあり、既存のものとともに CI で実行されます。- Rust SDK: V2 の bundle の検証者を
wasm機能からdcp_ai::v2::verify_bundle::verify_signed_bundle_v2に 移したため、ネイティブのビルドとcargo testがそれを実行します。wasm_verify_signed_bundle_v2はそれに委ねます。 tests/interop/v2/bundle_vectors.json: すべての V2 検証者が受け入れなければならない署名済み bundle と、変異 (偽造された bundle の PQ 署名、偽造された、または誤って帰属された成果物の署名、誤った枠のアルゴリズム、null や オブジェクトでない成果物)。変異の後は、bundle または成果物を示すエラーとともに拒否しなければならず、TypeScript、 Go、Rust のテストスイートで確認します。sdks/typescript/src/__tests__/generate-bundle-vectors.tsで再生成します。- Go SDK:
v2.SignPayloadは成果物に署名してSignedPayloadにします。複合署名、または PQ の鍵が与えられない 場合は古典のみの署名です。 - Python SDK:
MlKem768Provider(FIPS 203)。他の SDK がすでに持っていた ML-KEM-768 のプリミティブです。 Python の DCP-04 のハンドシェイクは、X25519 + ML-KEM-768 のハイブリッドの鍵交換をまだ実行しません。 - Python SDK: V2 の bundle。
BundleBuilderV2、sign_bundle_v2、sign_bundle_v2_classical_only、verify_signed_bundle_v2、DEFAULT_VERIFIER_POLICY、PQ_ONLY_VERIFIER_POLICYは、TypeScript のbuilder-v2.ts、signer-v2.ts、verify-v2.tsを移植したものです。検証者は各成果物の複合署名も確認し (VERIFICATION.md V2-8)、存在するのに不正な PQ 署名をどのモードでも拒否し(V2-7)、未知の検証モードに対して フェイルクローズします。TypeScript の検証者と違い、bundle の PQ チェックポイントをマニフェストのpq_checkpointsの ID に結び付け、max_session_duration_secondsの確認では、署名されていないsignature.created_atを検証時刻までに制限します。書き換えられた値でこの確認を短くできるのはセッションの残り 時間までであり、ゼロまでではありません。これを塞ぐには署名されたセッション開始時刻が必要ですが、マニフェストは それを持ちません。チェックポイントの内容(V2-12)とaudit_merkle_root_secondaryは、まだ検証されません。 tests/nist-kat/ml-kem-768とtests/nist-kat/slh-dsa-192f: NIST の ACVP ベクター(ML-KEM-768 の カプセル化解除と鍵の確認、SLH-DSA-SHA2-192f の署名検証)。tests/interop/v2/cross_sdk_vectors.json: TypeScript と Python の SDK が作成し、互いに相手のものを検証する、 SLH-DSA-192f、ML-KEM-768、署名済みの V2 bundle のベクター。
修正¶
- V2 の適合性テストの例(
scripts/generate-v2-examples.js)は、§12.1 が今では禁じている法的な名前から導出した ID ではなく不透明なhuman_idを使い、その RPR はpii_saltを持ちます。 - Python SDK:
BundleManifest.pq_checkpointsは、schemas/v2/bundle_manifest.schema.jsonと同じく チェックポイントの ID を持ち、モデルにsession_expires_atとintended_verifierを追加しました。
ドキュメント¶
spec/DCP-AI-v2.0.md§12.1 は、ソルト付きのコミットメント、完全な RPR と一緒にのみ開示される秘密のソルト、 完全な RPR の削除による消去、個人情報を含んだり個人情報から導出したりしてはならない(MUST NOT)不透明なhuman_id、ソルトのないコミットメントの非推奨化を規定します。spec/CANONICALIZATION_PROFILE.md、spec/DCP-AI-v2.0.md、WASM SDK の README(すべての言語)、docs/NIST_CONFORMITY.md、TypeScript、Python、Rust の正規化処理のコメントは、dcp-jcs-v1を、その厳密な 部分集合や RFC 8785 そのものではなく、RFC 8785 に基づくものとして記述します。規則 1 はキーをコードポイント順に 並べ、RFC 8785 は UTF-16 のコード単位で並べます。プロファイルは変わりません。- TypeScript SDK の README(すべての言語)と
docs/API_REFERENCE.mdは、複合署名、bundle、提示、PQ チェックポイント、A2A、エラー、緊急失効、鍵の回復、ハッシュ、CBOR の各関数の実際のシグネチャを列挙します。 docs/API_REFERENCE.md: V2 の検証パイプラインに成果物ごとの署名の確認を列挙し、V2-7 と V2-8 に関する既知の 制限の注記は、今では@dcp-ai/sdk2.1.2 以前にだけ当てはまります。- Go と WASM の SDK の README(すべての言語)と
docs/MIGRATION_V1_V2.mdは、bundle を作る前に各成果物に 署名し、パスポートと RPR に署名の鍵を列挙します。 spec/DCP-AI-v2.0.md§14.2 は上記の階層の計算を記述し、§14.3 と §14.4 はresolved_tierを情報提供のための ものとして記述し(§14.2 はそれを読まない)、spec/VERIFICATION.mdは §14.2 と同じように階層を計算します。 SDK の README(すべての言語)、docs/API_REFERENCE.md、クイックスタート、移行、エージェント作成のガイド、sdks/wasm/example.htmlは、階層の関数にポリシー決定を渡し、意図のスキーマの値を使います。spec/VERIFICATION.mdV2-7 とspec/DCP-AI-v2.0.md§7.1 は、検証者がすでにそうしているとおり、存在する PQ 署名はどのモードでも検証に成功しなければならないと述べています。docs/API_REFERENCE.mdはdetails.resolved_tierと、階層を考慮したverifySignedBundleV2のモードを文書化し、TypeScript SDK の README(すべての言語)がそれを説明します。docs/MIGRATION_V1_V2.md§6.3 は、CLI にないdcp migrate-checkコマンドや意図のrisk_scoreを示さなく なり、移行した bundle をdcp verify-bundle --policy hybrid_requiredで検証します。spec/DCP-AI-v2.0.md§14.3 は、V2 の検証者に対して階層の強制を MUST にします(§20.1)。モードはポリシーの モードと階層のモードのうち厳しい方です。spec/VERIFICATION.mdは、ステップ V2-9 で階層と実効的なモードを 計算し、ステップ V2-10 でそれを使ってポリシーを適用します。以前、階層の確認はそこで任意でした。docs/OPERATOR_GUIDE.mdとdocs/SECURITY_MODEL.mdは階層を考慮したモードを記述し、Go、Python、Rust、 WASM の SDK の README(すべての言語)は検証者ポリシーを記述します。- 仕様の §18(検証パイプライン)、
docs/OPERATOR_GUIDE.md、移行ガイドのステップ 8 は、検証者が実装している とおりに階層の強制を記述します。オペレーターガイドは、最上位の階層が PQ チェックポイントを検証するとは書かなく なりました(どの検証者もまだそれを行いません、V2-12)。また、@dcp-ai/sdkへの依存関係が更新されるまで リファレンスサーバーが何を強制するかを記しています。 spec/VERIFICATION.mdV2-3、V2-4、V2-13 は、payload_hash、フェイルクローズするマニフェストのハッシュ、 マニフェストに結び付いた監査証跡、セッションの有効期限、RPR のbinding_keysの有効性という、これらの確認を 明記しています。docs/API_REFERENCE.mdは、鍵の有効性のステップにバインディング鍵を列挙します。
[2.9.0] - 2026-10-21¶
パッケージのバージョン¶
dcp-ai(PyPI)2.8.1 → 2.8.2: 修正のみ。@dcp-ai/sdk(npm)2.1.1 → 2.1.2: 修正のみ。github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2v2.8.1 → v2.9.0:v2.MarshalCanonicalを追加。dcp-ai(crates.io)2.8.1 → 2.9.0: OpenTelemetry 0.32。省略可能なotlp機能については互換性のない変更です (「変更(互換性のない変更)」を参照)。- 変更なし:
@dcp-ai/wasm2.0.0、@dcp-ai/cli2.0.0、インテグレーションのパッケージ。
セキュリティ¶
- リファレンスの検証者(
lib/verify.js)、dcp verify-bundle、検証サーバーは、JSON Schema による検証の後、@dcp-ai/sdkのverifySignedBundleV2に委ねて、規範的な V2 の bundle (schemas/v2/signed_bundle.schema.json)を検証するようになりました。以前は、どの SDK が作った bundle も 「Invalid signed bundle format」として拒否され、dcp verify-bundleは偽造された bundle に対してV2 BUNDLE STRUCTURE VALID(終了コード 0)を出力し、サーバーは構造しか確認していませんでした。規範以前の エンベロープ(トップレベルのdcp_version/bundle_manifest)は拒否されます。サーバーは自らが公開するVERIFIER_POLICY(モード、受け入れるアルゴリズムと勧告で拒否されたアルゴリズム)で検証し、古典の署名者を 飛ばすpq_onlyモードでは公開鍵の固定を拒否します。 dcp sign-bundle --compositeは規範的なSignedBundleV2を出力します。ML-DSA-65 の kid は以前、秘密鍵の ハッシュから導出されていました。tools/bundle_sign.js --v2は削除しました。- 失効サービス: 1 件の緊急失効で、すべてのエージェントのすべての kid が失効したと報告されることはなくなり
(
GET /v2/check/kid/:kidは?agent_id=を受け取るようになりました)、不正な形式のパーセントエンコーディングは プロセスをクラッシュさせる代わりに 400 を返します。
変更(互換性のない変更)¶
lib/verify.js(ルートパッケージのmain):verifySignedBundleはasyncになり、4 番目の引数options({ policy, mode })を受け取ります。結果は常にerrors配列を持ちます。複合 GitHub Action のverify-bundle、bin/dcp.js、server/、tools/bundle_verify.jsを更新しました。tools/bundle_verify.jsは PQ の公開鍵の引数を受け取らなくなりました。- Rust SDK の省略可能な
otlp機能: OpenTelemetry 0.24 → 0.32。 - 上流の名前の変更に合わせて、
OtlpHandles.tracer_providerはSdkTracerProviderに、OtlpHandles.tracerはSdkTracerになりました。 - この機能は
tokioを取り込まなくなりました。ブリッジは SDK のバックグラウンドスレッドから、ブロッキングのreqwestクライアントでエクスポートします。 tracer install:で始まっていたエラーはtrace exporter:になりました。
追加¶
- Go SDK:
v2.MarshalCanonical(obj)。整数のみの規則を除いたdcp-jcs-v1のエンコーダーです。V1 のCanonicalizeと所持証明のエンコーダーは、今ではこれを使います。
修正¶
- Go SDK: V2、所持証明、V1 の経路で、正規化が
<、>、&、U+2028/U+2029 をエスケープしなくなり、-0を0として出力します(dcp-jcs-v1の規則 3 と 4)。 - TypeScript SDK: オブジェクトのキーを、UTF-16 のコード単位ではなく Unicode のコードポイントで並べます(規則 1)。
- Python SDK:
pqcryptoを 1.0 未満に制限しました。1.0 のリリースでpqcrypto.sign.ml_dsa_*モジュールが 削除されたため、dcp-ai2.8.1 を新たにインストールすると ML-DSA-65 のプロバイダーをインポートできません。 tests/interop/v2/interop_vectors.json: 負のゼロ、HTML の文字、U+2028/U+2029、制御文字のエスケープ、 Unicode の補助面の文字を含むキーの順序についての境界ケースのベクター。tools/conformance.js:edge_casesのエントリーが何も確認せずに合格することはなくなり、一度も実行されない ドメイン分離のブロックを削除し、V2 の署名済み bundle(有効、改ざん、偽造、PQ の剥ぎ取り、鍵の固定、従来形式)を リファレンスの検証者で確認します。
依存関係¶
- Dependabot の未解決のアラート 95 件をすべて解消しました(重大 11 件、高 54 件)。#22 が Dependabot の 15 件の PR(#5–#21)に取って代わり、#24 が grpc を更新しました。
- TypeScript SDK、
@dcp-ai/express、@dcp-ai/openclaw(開発用): - vitest と
@vitest/coverage-v84.1.12(同時に更新)。 - vite 7.3.7(
overridesで固定)。 - postcss 8.5.31、nanoid 3.3.20、source-map-js 1.2.2、esbuild 0.28.2、fast-uri 3.1.9。
- Express の実行時のロックファイル: proxy-addr 2.0.8、qs 6.16.1、body-parser 2.3.0。
- ルートのハーネス: fast-uri 3.1.9 と、新しい依存関係
@dcp-ai/sdk。 - Go SDK:
golang.org/x/cryptov0.55.0、golang.org/x/netv0.58.0、google.golang.org/grpcv1.83.2、go.opentelemetry.io/otel/*v1.46.0。 - Rust SDK: opentelemetry、opentelemetry_sdk、opentelemetry-otlp 0.32。
opentelemetry_sdk0.32.1 は、W3C Baggage の伝播における無制限のメモリー確保を修正します。 - CI:
- express と openclaw のための新しいインテグレーションテストのジョブ。
- Rust のジョブは
--features otlpをビルドしてテストします。 - Go のジョブはバージョンを
go.modから読みます。 - 生成した V2 の bundle を CLI で検証します。
- サーバーと失効のテストを実行します。
ドキュメント¶
spec/VERIFICATION.md:- V2 のチェックリストは
schemas/v2/signed_bundle.schema.jsonを指すようになりました(引用されていた*_v2のスキーマは存在したことがありません)。 - 存在しないバインディング
independentを削除しました。 - リファレンス実装の名前を記しました。
spec/CANONICALIZATION_PROFILE.md§3 に、文字列のエスケープとコードポイント順のキーの並びについての行を追加しました。これは規則 1 と 3 を明確にするもので、プロファイルは変わりません。- サーバー、オペレーター、移行、API リファレンス、CI、bundle のドキュメントは、実際の V2 の検証、実際の CLI の構文、実在する SDK の API を記述するようになりました。
- 移行ガイドの API の表には、存在しない関数がいくつも載っていました。
- サーバーの README は規範以前のエンベロープを示していました。
- Python SDK の README(すべての言語)は ML-KEM-768 や V2 の bundle に対応しているとは書かなくなり、CrewAI のクイックスタートは V2 のスニペットを予定の API として明示しています。
- 翻訳とプロジェクトのドキュメント:
- Agno を含む 11 のインテグレーション。正規化プロファイルと Agno のクイックスタートへのリンク。
- このリリースの Rust のインストールのスニペットと、Go の
@latestの固定。 SECURITY.mdのパッケージごとのサポート対象バージョンと、ROADMAP.mdの v2.8.x と v2.9.0 のリリース。CITATION.cffの Zenodo のコンセプト DOI。
[2.8.1] - 2026-04-26¶
4 つの SDK すべてで canonicalization_profile フィールドを配線¶
v2.8.0 は canonicalization_profile フィールドを
schemas/v2/bundle_manifest.schema.json で宣言し、
spec/CANONICALIZATION_PROFILE.md § 4 で説明しましたが、実際にこのフィールドを書いたり読んだりする SDK はありません
でした。型付きの BundleManifest 構造はこのフィールドなしで出荷され、検証者はそれを無視していました。v2.8.1 は
この空白を端から端まで埋めます。
- TypeScript(
@dcp-ai/sdk2.1.0 → 2.1.1):sdks/typescript/src/types/v2.tsのBundleManifestインターフェースにcanonicalization_profile?: 'dcp-jcs-v1'を追加しました。sdks/typescript/src/bundle/builder-v2.tsのBundleBuilderV2.build()は、作成するすべてのマニフェストにcanonicalization_profile: "dcp-jcs-v1"を出力するようになりました。sdks/typescript/src/core/verify-v2.tsのverifyV2Bundleは、フィールドがない場合を受け入れ(dcp-jcs-v1と みなす)、"dcp-jcs-v1"を明示的に受け入れ、それ以外の値を"Unknown canonicalization_profile: <value>"で拒否します。 - Python(
dcp-ai2.8.0 → 2.8.1):sdks/python/dcp_ai/v2/models.pyのBundleManifestにcanonicalization_profile: Literal["dcp-jcs-v1"] | None = "dcp-jcs-v1"を追加しました。 Pydantic が解析時に未知の値の拒否を強制し、フィールドがない場合は既定値が使われます。検証はモデルの中に あるため、検証者を別に変更する必要はありません。 - Go(
sdks/go/v2.8.0→v2.8.1):sdks/go/dcp/v2/types.goのBundleManifest構造体に、json:"canonicalization_profile,omitempty"を付けたCanonicalizationProfile stringを追加しました。sdks/go/dcp/v2/bundle_builder.goのBuildBundleV2は、作成するすべてのマニフェストでこれを"dcp-jcs-v1"に設定します。sdks/go/dcp/v2/verify_bundle.goのVerifySignedBundleV2は、マニフェストが"dcp-jcs-v1"以外のcanonicalization_profileの値を持つ bundle を拒否するようになりました。 - Rust(crates.io の
dcp-ai2.8.0 → 2.8.1):sdks/rust/src/v2/types.rsのBundleManifestに、#[serde(skip_serializing_if = "Option::is_none")]を付けたpub canonicalization_profile: Option<String>を追加しました。sdks/rust/src/lib.rsのwasm_build_bundleは、出力するマニフェストに"canonicalization_profile": "dcp-jcs-v1"を設定します。
仕様とプロファイルの文書¶
spec/DCP-AI-v2.0.md§ 9(bundle マニフェスト)は、マニフェストの他のフィールドと並べてcanonicalization_profileを列挙するようになり、フィールドがない場合は"dcp-jcs-v1"と同等とみなさなければ ならない(MUST)というインラインの注記を付けました。spec/CANONICALIZATION_PROFILE.md§ 2: 規則 6(undefined / null の扱い)を、TypeScript、Python、Go、Rust の ホストの値が、オブジェクトの位置と配列の位置の両方で JSON のワイヤーフォーマットにどう対応するかを明示的に 列挙する、言語横断の表として書き直しました。spec/CANONICALIZATION_PROFILE.md§ 2: 新しい規則 9 は、Unicode の正規化(NFC、NFD、NFKC、NFKD)を明示的に 範囲外とします。正規化処理は、ホストのパーサーが渡したとおりに文字列をバイト単位で出力し、将来のプロファイル (dcp-jcs-v2以降)は正規化の形式を固定してもかまいません(MAY)。アプリケーション層での正規化の慣例的な選択 (NFC)として RFC 8259 § 8.1 を参照しています。spec/CANONICALIZATION_PROFILE.mdの規則 9 は、NaN/±Infinityの相互運用性のフィクスチャを提供しない理由も 定めています。これらの値は RFC 8259 のワイヤーフォーマットの一部ではないため、ほとんどのパーサーは正規化処理に 届く前にそれらを拒否します。拒否は、共有のフィクスチャではなく、SDK ごとのユニットテストで確認します。
動作の互換性¶
新しいフィールドは追加的で、シリアライズにおいて省略可能です。
v2.8.1が作成した bundle は、マニフェストにcanonicalization_profile: "dcp-jcs-v1"を持ちます。このフィールドを知らない古い検証者は、それを未知のプロパティとして扱いますが、 JSON Schema がこのフィールドをadditionalPropertiesと両立するものとして宣言している(propertiesの中に あり、optionalである)ため、問題ありません。v2.8.0以前が作成した bundle にはcanonicalization_profileフィールドがありません。v2.8.1の検証者は それを受け入れます。spec/CANONICALIZATION_PROFILE.md§ 4 によれば、フィールドがない場合は"dcp-jcs-v1"と 同等とみなさなければなりません(MUST)。- 未知の値(たとえば
"dcp-jcs-v2")のcanonicalization_profileを持つ bundle は、v2.8.1のすべての SDK が 拒否します。これは将来のプロファイルに向けた前方互換性のための仕掛けです。新しいプロファイルに更新されていない 検証者は、検証できないマニフェストを黙って受け入れるのではなく、それを拒否しなければなりません(MUST)。
bundle レベルの署名は canonical(manifest) を対象とするため、このフィールドを追加すると、新たに作成した bundle の
マニフェストのハッシュは、v2.8.0 のもとで作成した場合とは変わります。v2.8.0 以前で作成した bundle と、その
保存済みの署名は、v2.8.1 の検証者のもとでも引き続き有効です。
更新したバージョン¶
dcp-ai(PyPI)2.8.0 → 2.8.1dcp-ai(crates.io)2.8.0 → 2.8.1github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2v2.8.0 → v2.8.1@dcp-ai/sdk(npm)2.1.0 → 2.1.1: 2.1.0 以来の最初の TypeScript のコード変更 (2.8.0 のリリースは docstring の編集のみでした)
[2.8.0] - 2026-04-26¶
追加 — 正規化プロファイル dcp-jcs-v1¶
別のプロトコルとの公開の比較によって、4 つの SDK の JSON の正規化に 3 つの実際の非対称性があることが明らかに
なりました。1.0/1.00 は Python と Rust では拒否され、TypeScript と Go では受け入れられていました。
1e2 は Rust だけが拒否していました。undefined には仕様上の正式な扱いがありませんでした。
spec/DCP-AI-v2.0.md § 15 の「RFC 8785 + 整数のみ」という要約は、その範囲では正しかったものの、JCS が実装に
委ねている場合を固定していませんでした。このリリースはそれらをすべて解消します。
- 新しい規範的な文書:
spec/CANONICALIZATION_PROFILE.mdは、番号付きの 8 つの規則、22 の入力を扱う境界ケースの受け入れ表、TypeScript だけの非対称性(オブジェクトでは 省略し、配列ではnullとしてシリアライズ)を文書化した undefined の扱いの取り決め、将来のプロファイルの ためのバージョン管理の方針によって、プロファイルdcp-jcs-v1を形式化します。 - bundle マニフェストのフィールド:
canonicalization_profile: "dcp-jcs-v1"をschemas/v2/bundle_manifest.schema.jsonに省略可能なフィールドとして追加しました。このフィールドのない bundle を受け取った検証者はdcp-jcs-v1とみなさなければなりません(MUST)。将来のプロファイルでは、この フィールドは必須になります。 - Python(
dcp-ai2.7.1 → 2.8.0):assert_no_floatsは、値が有限の整数である浮動小数点数(1.0、1e2、1.00)を受け入れるようになりました。それらはjson.dumpsの前に整数の形に正規化されます。整数でない浮動 小数点数(0.1)、NaN、無限大は引き続き拒否されます。 - Rust(
dcp-ai2.7.0 → 2.8.0):assert_no_floatsは、fract()がゼロであるNumber(f64)を受け入れる ようになりました。canonical_recurseの新しいヘルパーformat_numberは、整数値の浮動小数点数を小数点も指数も なしで出力し、他の SDK とバイト単位で一致させます。 - Go(
sdks/go/v2.7.0→v2.8.0): 動作はすでにそろっていました(v != math.Trunc(v)の確認)。 バージョンの更新のみです。 - TypeScript(
@dcp-ai/sdkは 2.1.0 のまま): 動作はすでにそろっていました。sdks/typescript/src/core/canonicalize.tsの docstring で、undefined と null の非対称性を形式化しました。
追加 — 境界ケースの相互運用性フィクスチャ¶
tests/interop/v2/interop_vectors.json に canonicalization.edge_cases を追加しました。14 個のベクターで、null
の保持(キー付き、配列内)、整数値の浮動小数点数、末尾のゼロ、指数表記、小数の拒否、有限でない値の拒否、
コードポイントによるキーの並べ替え(é を含む)、入れ子の null、空のコンテナー、深く入れ子になったオブジェクト、
null を含む配列を扱います。各 SDK の相互運用性テストは同じブロックを読み込み、すべてのベクターについてバイト単位で
同一の出力(または一致するエラー)を確認します。CI はすべての PR で 4 つを並行して実行し、相違があればリリースを
止めます。
更新したバージョン¶
dcp-ai(PyPI)2.7.1 → 2.8.0dcp-ai(crates.io)2.7.0 → 2.8.0github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2→ v2.8.0@dcp-ai/sdk(npm)は 2.1.0 のまま: TypeScript はすでにこのプロファイルを実装しており、このリリースでは docstring による形式化だけを追加します。
動作の互換性¶
以前のリリースで作成した bundle は引き続き有効です。以前 1.0/1.00/1e2 を拒否していた SDK にとって、この
変更は追加的です。以前は TypeError/Err を投げていた入力が成功するようになり、他の SDK がすでに作成していた
のと同じ正規の出力を作ります。以前に正規化に成功していた入力が、2.8.0 で異なる形に正規化されることはありません。
[2.7.1] - 2026-04-23(Python のみ)¶
修正¶
dcp-ai(PyPI)2.7.0 には、必須の依存関係としてcryptographyが欠けていました。このパッケージは、2.5.0 で 導入された DCP-04 の A2A セッション層が AES-256-GCM の暗号化のために必要とします。pip install dcp-ai==2.7.0による新規のインストールではcryptographyが入らず、クリーンな環境で A2A セッションの 3 つのテスト (test_encrypt_decrypt_round_trip、test_tamper_ciphertext_rejected、test_session_id_mismatch)が失敗して いました。2.7.1 は wheel の必須の依存関係にcryptography>=41.0を追加します。
Rust(crates.io の dcp-ai)と Go(sdks/go/v2)は影響を受けず、2.7.0 のままです。Python の cryptography
パッケージが関係するのは Python の wheel だけです。
[2.7.0] - 2026-04-23¶
追加 — PY / GO / RS における正規のエラーコードとワイヤーフォーマットの判定¶
DcpErrorCode 列挙型と、それに付随する DcpError / DcpProtocolError の仕組みを、TS から Python、Rust、Go に
移植し、さらに、入ってくるバイト列を先頭のバイトに基づいて "json" または "cbor" に振り分ける軽量なヘルパー
detect_wire_format を移植しました。
すべての SDK が同じ 38 個の正規のエラーコードで一致するようになりました。 対象は、スキーマのエラー
(E001-E099)、署名のエラー(E100-E199)、ハッシュとチェーンのエラー(E200-E299)、アイデンティティのエラー
(E300-E399)、ポリシーのエラー(E400-E499)、セッションのエラー(E500-E599)、A2A のエラー(E600-E699)、
レート制限(E700-E799)、内部エラー(E900-E999)です。各コードは正規のメッセージと retryable フラグを持つため、
クライアントはポリシーに合った再試行のロジックを SDK 間で一貫して実装できます。
Python(dcp-ai 2.6.0 -> 2.7.0): 新しいモジュール dcp_ai.v2.error_codes。DcpErrorCode(str-enum)、
DcpError データクラス、DcpProtocolError 例外、create_dcp_error、is_dcp_error、detect_wire_format、
ERROR_DESCRIPTIONS の対応表を含みます。
Rust(dcp-ai 2.6.0 -> 2.7.0): dcp_ai::v2::error_codes。DcpErrorCode 列挙型(Display → 安定した
識別子 DCP-E###)、DcpError 構造体、create_dcp_error、detect_wire_format を含みます。
Go(sdks/go/v2.6.0 -> v2.7.0): 37 個の Err* 定数を持つ型付き文字列 v2.DcpErrorCode、error
インターフェースを実装する v2.DcpError 構造体、CreateDcpError、IsDcpError、DetectWireFormat。
CBOR エンコーダー/デコーダーの範囲についての決定¶
完全な CBOR エンコーダー/デコーダーは、2.x では引き続き TypeScript だけのものです。決定的な RFC 8949 の実装を
さらに 3 つの SDK に移植するのは、独自のマイルストーンに値する大きなプロジェクトです。detect_wire_format は、
CBOR のペイロードを既存のエコシステムのライブラリ(たとえば Python の cbor2、Go の
github.com/fxamacker/cbor/v2、Rust の ciborium)に振り分けるために、今すべての SDK が必要とする唯一の
ヘルパーです。専用の v3.x のリリースで正規の移植を追加します。
テストの件数¶
- Python: 231/231 合格(変更なし、インポートの範囲を確認)
- Rust: 152/152 合格(新規 +5)
- Go: 115/115 合格(新規 +8)
更新したバージョン¶
dcp-ai(PyPI)2.6.0 -> 2.7.0dcp-ai(crates.io)2.6.0 -> 2.7.0github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2-> v2.7.0
[2.6.0] - 2026-04-23¶
追加 — Rust と Go におけるブラインド化された RPR、マルチパーティの認可、勧告のヘルパー¶
Python だけにあった 3 つの機能を Rust と Go に移植し、比較で指摘された、Python が TS 以外の他の SDK より先行して いた差を埋めます。
- ブラインド化された RPR(Gap #2):
compute_pii_hash、blind_rpr、verify_blinded_rpr、is_blinded_rpr。 - マルチパーティの認可(Gap #5):
verify_multi_party_authorization - 4 つの既定の操作ポリシー(
revoke_agent、rotate_org_key、change_jurisdiction、modify_recovery_config)を持つMultiPartyPolicy。 - アルゴリズム勧告のヘルパー(Gap #4):
check_advisory、evaluate_advisories、apply_advisories_to_policy、build_algorithm_advisory。
3 つのモジュールはすべて Python の意味に合わせています。個人情報の SHA-256 コミットメント、M-of-N の構造的な
検証(暗号学的な検証はゲートウェイで行う)、猶予期間の扱いを伴うアクション(revoke / deprecate / warn)に
よる振り分けです。
Python(dcp-ai 2.5.0 -> 2.6.0): コードの変更はなく、SDK 一式をそろえるためのバージョンの更新のみです。
テストの件数¶
- Rust: 147/147(新規 +14)
- Go: 106/106(新規 +12)
- Python: 231/231(変更なし)
[2.5.0] - 2026-04-23¶
追加 — DCP-04 エージェント間プロトコルの同等性¶
DCP-04(エージェント間通信)の骨組みを残りの SDK に移植します。
Python(dcp-ai 2.4.0 -> 2.5.0): 対称鍵のセッション層(cryptography パッケージによる AES-256-GCM)を
含め、TS と完全に同等です。
- 発見:
create_agent_directory、find_agent_by_capability、find_agent_by_id、validate_directory_entry。 - ハンドシェイク:
generate_nonce、create_hello、create_welcome、derive_session_id、create_close_message。 - セッション:
A2ASession、create_session、encrypt_message、decrypt_message、needs_rekeying、generate_resume_proof、verify_resume_proof、derive_rekeyed_session_key。
Go(sdks/go/v2.4.0 -> v2.5.0): AES-256-GCM に Go の標準ライブラリの crypto/aes + crypto/cipher を
使い(新しい依存関係なし)、TS と完全に同等です。
Rust(dcp-ai 2.4.0 -> 2.5.0): 発見とハンドシェイクの骨組み。AES-256-GCM のセッション層は後続のリリースで
予定しています。Rust の利用者は、ディレクトリと HELLO/WELCOME のメッセージを作り、セッション ID を導出することは
できます。
テストの件数: Python 231/231、Rust 133/133、Go 94/94。
[2.4.0] - 2026-04-23¶
追加 — Python、Rust、Go における本番運用向けの強化プリミティブ¶
TS のコアから、プロトコルにとって重要な 4 つの強化プリミティブを移植します。
- セッション nonce のヘルパー:
generate_session_nonce、is_valid_session_nonce、verify_session_binding、generate_session_expiry、is_session_expired。 - 適応型のセキュリティ階層:
compute_security_tier、max_tier、tier_to_verification_mode、tier_to_checkpoint_interval(Go にはすでにComputeSecurityTierがあり、v2.4 では 3 つのヘルパー関数を追加)。 - 緊急失効(Gap #13):
generate_emergency_revocation_token、verify_emergency_revocation_secret、build_emergency_revocation。 - 遅延型の PQ チェックポイント:
audit_events_merkle_root、create_pq_checkpoint、 および階層に応じた間隔の選択と自動フラッシュの動作を持つPQCheckpointManagerクラス。
4 つのモジュールはすべて TS の意味と完全に一致しています。緊急失効のための定数時間での秘密の検証、階層に応じた
チェックポイントの間隔、セッション nonce の検証用の正規表現、DCP-AI.v2.AuditEvent のドメイン分離コンテキスト
のもとで署名されたチェックポイントのペイロードです。
v2.4 に含まれないもの¶
意図的に範囲外としたもの(需要があれば後続のリリースで提供します):
- Shamir の秘密分散(Gap #1): 慎重な暗号のレビューが必要。TS のみ。
- 検証キャッシュ: アプリケーションの関心事であり、プロトコルの関心事ではない。
- レート制限 / サーキットブレーカー / 再試行: 既存のエコシステムのライブラリに委ねるのがよい、アプリケーション レベルのパターン。
テストの件数¶
- Python: 214/214 合格(新規 +24)
- Rust: 126/126 合格(新規 +10)
- Go: 81/81 合格(新規 +9)
更新したバージョン¶
dcp-ai(PyPI)2.3.0 -> 2.4.0dcp-ai(crates.io)2.3.0 -> 2.4.0github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2-> v2.4.0
[2.3.0] - 2026-04-23¶
追加 — SDK 間での紛争、権利、委任の同等性¶
Python、Rust、Go は、TypeScript の機能群に合わせて、DCP-07(紛争の解決 + 仲裁)、DCP-08(権利と義務)、DCP-09 (委任、認識しきい値、プリンシパルミラー)の動作を実装するようになりました。
新しい関数群(PY/RS/GO で意味が同一で、TS に一致):
DCP-07 の紛争の解決:
create_dispute·escalate_dispute·resolve_dispute·create_objection- 仲裁:
create_arbitration_panel·submit_resolution·build_jurisprudence_bundle·lookup_precedent
DCP-08 の権利と義務:
declare_rights·record_obligation·report_violation·check_rights_compliance
DCP-09 の委任と代理:
- 委任:
create_delegation_mandate·verify_mandate_validity·revoke_delegation·generate_interaction_record - 認識しきい値:
evaluate_significance·should_notify_human·create_awareness_threshold·create_advisory_declaration - プリンシパルミラー:
generate_mirror
新しいファクトリーはすべて、DCP-AI.v2.Dispute、DCP-AI.v2.Rights、DCP-AI.v2.Delegation、
DCP-AI.v2.Awareness のドメイン分離コンテキストのもとで、既存の複合署名の経路を使います。委任マンデートの
成果物は、TS のワイヤーフォーマットに合わせて、人間のプリンシパルの署名を human_composite_sig フィールドに
持ちます。
テストの件数¶
- Python: 190/190 合格(新規 +21)
- Rust: 116/116 合格(新規 +12)
- Go: 72/72 合格(外側の
dcp_testパッケージで新規 +12) - TypeScript: 460/460 合格(変更なし)
更新したバージョン¶
dcp-ai(PyPI)2.2.0 -> 2.3.0dcp-ai(crates.io)2.2.0 -> 2.3.0github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2-> v2.3.0@dcp-ai/sdk(npm)は 2.1.0 のまま
[2.2.0] - 2026-04-23¶
追加 — SDK 間でのライフサイクルと承継の同等性¶
Python、Rust、Go の SDK は、DCP-05(エージェントのライフサイクル)と DCP-06(デジタル承継)の動作を実装するように なりました。TypeScript は 2.0.x ですでにこれらを提供していました。2.2.0 のリリースは、SDK 間の比較で特定された 最初の動作の同等性の差を埋めます。
新しい関数(Python/Rust/Go で意味が同一で、TS に一致):
DCP-05 エージェントのライフサイクル:
validate_state_transition/ValidateStateTransitioncompute_vitality_score/ComputeVitalityScorecreate_commissioning_certificate/CreateCommissioningCertificatecreate_vitality_report/CreateVitalityReporthash_vitality_report/HashVitalityReportcreate_decommissioning_record/CreateDecommissioningRecord
DCP-06 デジタル承継:
create_digital_testament/CreateDigitalTestamentupdate_digital_testament/UpdateDigitalTestamentclassify_memory/ClassifyMemorycreate_memory_transfer_manifest/CreateMemoryTransferManifestexecute_succession/ExecuteSuccession
新しいファクトリーはすべて、DCP-AI.v2.Lifecycle と DCP-AI.v2.Succession のドメイン分離コンテキストのもとで
既存の複合署名の経路を使うため、どの SDK が作った成果物もワイヤー上で互換性があり、相互に検証できます。
このリリース後のテストの件数¶
- Python: 169/169 合格(新規 +24)
- Rust: 104/104 合格(新規 +10)
- Go: 60/60 合格(外側の
dcpパッケージで新規 +13、v2 パッケージは変更なし) - TypeScript: 460/460 合格(変更なし)
プロトコルレベルの既知の注記¶
DCP v2.0 の正規化は、SDK 間の決定性のために浮動小数点数を禁じていますが、バイタリティレポートのスキーマは指標ごとの
値を number(0.0..1.0)として表しています。4 つの SDK すべてのファクトリーは API の境界では指標を受け付けるように
なりましたが、署名者はワイヤー上では整数の表現を必要とします。このことは各 SDK のテストに記されています。将来の
リリースでは、この差を完全になくすために、スキーマを整数(またはベーシスポイント)に厳格化する可能性があります。
更新したバージョン¶
dcp-ai(PyPI)2.1.0 -> 2.2.0dcp-ai(crates.io)2.1.0 -> 2.2.0github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2-> v2.2.0@dcp-ai/sdk(npm)は 2.1.0 のまま(TS はすでにこれらの関数を持っていました)
[2.1.0] - 2026-04-22¶
追加¶
4 つのコア SDK すべてに OpenTelemetry(OTLP)エクスポーターを追加: TypeScript、Python、Rust、Go。採用者は、手作りのブリッジなしで、DCP の可観測性を OTel 互換の任意のバックエンド(Grafana、Jaeger、Honeycomb、Datadog、New Relic、セルフホストの Collector)に送れるようになりました。DCP の暗号処理を行うすべての SDK が、同じメトリクス名、カウンター、スパンの形を報告します。
-
Rust(
dcp-ai2.0.0 → 2.1.0)- スレッドセーフな
DcpTelemetryシングルトン、記録用のメソッド、スパンのライフサイクル、on_eventのリスナーバス、p50/p95/p99 を持つMetricsSummaryを備えた新しいモジュールdcp_ai::observability。 - 省略可能な Cargo の機能
otlp(cargo add dcp-ai --features otlp)は、opentelemetry、opentelemetry_sdk、opentelemetry-otlp、tokioを取り込みます。この機能がない場合、ExporterType::Otlpを要求するとパニックせずに明確なエラーイベントを出します。 - 計測したホットパス:
crypto::sign_objectとcrypto::verify_objectは、有効なときにレイテンシーとエラーのテレメトリーを出します。無効なとき(既定)はオーバーヘッドがありません。 - 既定で無効な動作、パーセンタイル、スパンのライフサイクル、階層の分布、キャッシュヒット率、リスナーのパニックの隔離を扱う 10 個のユニットテスト。
- スレッドセーフな
-
Go(
sdks/go/v2.0.0 → v2.1.0)- ミューテックスで保護された
Telemetry型、Default()シングルトン、記録用のメソッド、パニックから回復するサブスクライバー、他の SDK と一致するパーセンタイルの計算を備えた新しいパッケージgithub.com/dcp-ai-protocol/dcp-ai/sdks/go/v2/dcp/observability。 - OTLP のブリッジはビルドタグ
otlp(go build -tags otlp)で有効になります。タグがない場合、ExporterOTLPを要求するとリスナーバスを通じて明確なotlp_initのエラーイベントを出します。go.opentelemetry.io/otelの依存関係はgo.modに記載されていますが、既定のビルドでは実行時に必要ありません。 - 計測したホットパス:
dcp.SignObjectとdcp.VerifyObjectは、有効なときにレイテンシーとエラーのテレメトリーを出します。無効なとき(既定)はオーバーヘッドがありません。 - 可観測性のパッケージの 10 個のユニットテストと、有効と無効の経路を扱う
dcp.SignObjectに対する 2 個のインテグレーションテスト。
- ミューテックスで保護された
-
TypeScript(
@dcp-ai/sdk2.0.0 → 2.1.0)dcpTelemetry.init({ exporterType: 'otlp' })が実際に動作するようになりました(設定のフィールドは 2.0.x で宣言されていましたが、配線されていませんでした)。- OTel の SDK は遅延してインポートされるため、既定のインストールは変わりません。
@opentelemetry/*パッケージは省略可能な peer 依存関係として宣言されています。ない場合、init()はリスナーバスを通じて明確なエラーイベントを出し、アプリケーションは動作を続けます。 - 保留中のエクスポートを送り出すための新しい
dcpTelemetry.shutdown()。 - エンドポイントの解決: 設定の
otlpEndpoint→ 環境変数OTEL_EXPORTER_OTLP_ENDPOINT→http://localhost:4318。 - リソース属性
service.name+service.versionを自動的に設定します。 - メトリクスの対応: DCP の記録はヒストグラム(
dcp.sign.latency_ms、dcp.verify.latency_ms、dcp.kem.latency_ms、dcp.checkpoint.latency_ms、dcp.bundle_verify.latency_ms)とカウンター(dcp.signatures.created、dcp.signatures.verified、dcp.bundles.verified、dcp.a2a.sessions、dcp.errors)に対応します。 - vitest の新しいケースが 2 件。460/460 のテストに合格。
-
Python(
dcp-ai2.0.2 → 2.1.0)- TypeScript 版と同じ API を持つ
dcp_telemetryシングルトンを提供する新しいモジュールdcp_ai.observability。スパン、メトリクスの記録(record_sign_latency、record_verify_latency、record_kem_latency、record_checkpoint_latency、record_bundle_verify、record_cache_hit/miss、record_a2a_*、record_error)、on_eventのリスナーバス、p50/p95/p99 を持つget_metrics_summaryを備えます。 - エクスポーターのモード:
none(既定)/console/otlp。 - 新しいインストールの extra:
pip install 'dcp-ai[otlp]'はopentelemetry-sdk+opentelemetry-exporter-otlp-proto-httpを取り込みます。extra がない場合、init(exporter_type="otlp")はクラッシュせずに明確なインストールの案内を表示します。 - 計測したホットパス:
sign_objectとverify_objectは、有効なときにレイテンシーとエラーのテレメトリーを出すようになりました。無効なとき(既定)はオーバーヘッドがありません。 - 公開のエクスポート:
from dcp_ai import dcp_telemetryが使えます。 - pytest の新しいケースが 15 件。145/145 のテストに合格。
- TypeScript 版と同じ API を持つ
ドキュメント¶
- コピーして使える 3 つのバックエンドのレシピ(Docker によるローカルの Jaeger、Grafana Cloud の OTLP エンドポイント、Honeycomb)を含む新しい
docs/OBSERVABILITY.md。
後方互換性¶
- 4 つの SDK すべてで完全に後方互換です。既定値は変わりません。テレメトリーは無効の状態で出荷され、記録は何もしません。可観測性を望まない採用者はコードを変更する必要がありません。
- semver を同期:
@dcp-ai/sdk(npm)、dcp-ai(PyPI)、dcp-ai(crates.io)、github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2はすべて 2.1.0 になります。その他の公開可能なパッケージ(CLI、WASM、インテグレーション、create-* のひな形)は現在のバージョンのままです。 - WASM SDK の可観測性は将来のマイナーリリースに延期します。ブラウザーのテレメトリーには異なる転送の要件があります。
テンプレートのパッケージ - 2026-04-21¶
4 つの npm create @dcp-ai/* ひな形を初めて公開しました。すべて v2.0.0 です。
@dcp-ai/create-langchain@dcp-ai/create-crewai@dcp-ai/create-openai@dcp-ai/create-express
使い方: npm create @dcp-ai/langchain my-app(または 4 つのいずれか)。各ひな形は、リポジトリの既存の templates/<name>/ と同じ内容の自己完結したスターターテンプレートと、実行時の依存関係のない 35 行の小さな bin.js を含みます。
インフラストラクチャー¶
- JSON-LD コンテキストを
https://dcp-ai.org/credentials/v2で提供するようになりました(Content-Typeapplication/ld+json、CORS*、24 h のキャッシュ)。@dcp-ai/w3c-didがこれを必要とし、発行されるすべての Verifiable Credential/Presentation を厳格な JSON-LD プロセッサー(Veramo、SpruceID、Trinsic)が参照解決できるようにします。 - 4 つの SDK(TypeScript、Python、Go、Rust)の Codecov のカバレッジレポートを、SDK ごとのフラグ付きで集約しました。README にバッジを掲載しています。
- 公開のワークフローを強化: すべてのジョブ(npm / PyPI / crates.io)が先にレジストリを確認し、マニフェストのバージョンがすでに公開済みであれば、スキップの通知とともに成功で終了します。日常のリリースでジョブが赤くなることはなくなりました。
Go SDK v2.0.0 - 2026-04-19¶
go get でインストールできる Go SDK の最初のリリースです。以前のモジュールパス(github.com/dcp-ai/dcp-ai-go)は存在しないリポジトリを指していたため、外部の利用者はインストールできませんでした。モジュールは今ではこのモノレポ内のサブディレクトリのモジュールとして置かれています。
- 新しいモジュールパス:
github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2(メジャーバージョン ≥ 2 では Go が/v2の接尾辞を要求する) - タグの形式:
sdks/go/v2.0.0(マルチモジュールのリポジトリについて Go のモジュールプロキシが要求するとおり、サブディレクトリの接頭辞付き) - インストール:
go get github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2@v2.0.0
コードは変わりません。書き直したのはモジュールパスと内部のインポートだけです。すべてのテストに引き続き合格します。
[2.0.2] - 2026-04-18¶
Python SDK¶
- 修正:
dcp_ai.__version__は、固定の文字列ではなくimportlib.metadataを通じて、インストールされたバージョンを動的に反映するようになりました。2.0.1 では、wheel が2.0.1であるにもかかわらず、この属性は"1.0.0"を報告していました。
CI / 公開のワークフロー¶
- すべての公開のジョブ(
publish.yml、publish-pypi.yml、publish-integrations.yml)は、マニフェストのバージョンがすでにレジストリにあるかを先に確認し、あればスキップの通知とともに成功で終了するようになりました。以前は、リリースで起動された実行がすでに公開済みのバージョンを再び公開しようとし、Actions タブに 4 つの赤いジョブを残していました。日常のリリースで見た目だけの赤い亡霊が出ることはなくなりました。 - README のインテグレーションの表にあった 2 つの古いパッケージ名を修正しました:
@dcp-ai/a2a→@dcp-ai/google-a2a、@dcp-ai/mcp→@dcp-ai/anthropic-mcp。 - インテグレーションの表の各行に、npm / PyPI のバージョンを示すライブのバッジを追加しました。
[2.0.1] - 2026-04-18¶
Python SDK¶
フレームワークとのブリッジをパッケージの中に同梱するようになりました。2.0.1 より前は、それらはリポジトリの
integrations/<name>/ にあり、pytest の小細工を通じてしか読み込めませんでした。pip install dcp-ai[fastapi] を
実行した人は、上流の fastapi ライブラリは得られても、dcp_ai.fastapi のミドルウェアは得られませんでした。
2.0.1 はこれを修正します。4 つのモジュールは今では dcp_ai/ の下にあり、公開される wheel に含まれます。
- 追加:
dcp_ai.fastapi(ミドルウェア、依存性注入、V2 の構造の確認) - 追加:
dcp_ai.langchain(エージェントのラッパー、コールバック、リスクのスコア付け) - 追加:
dcp_ai.openai(クライアント、ツールのスキーマ、監査証跡のビルダー) - 追加:
dcp_ai.crewai(クルーのエージェント、結合した監査証跡、セッションの一貫性の確認) - 削除:
tests/conftest.pyの動的なモジュールローダー(不要になったため)
インストール¶
pip install dcp-ai[fastapi] # brings fastapi + uvicorn
pip install dcp-ai[langchain] # brings langchain + langchain-core
pip install dcp-ai[openai] # brings openai
pip install dcp-ai[crewai] # brings crewai
後方互換性¶
2.0.0 のインポートと完全に互換性があります。新しいモジュールは API を追加するだけで、既存の
from dcp_ai import ... の呼び出しには影響しません。
[npm integrations] - 2026-04-18¶
6 つのフレームワークとのブリッジを、独立した npm パッケージとして初めて公開しました。すべて v2.0.0 です。
@dcp-ai/anthropic-mcp— Anthropic MCP とのブリッジ@dcp-ai/autogen— Microsoft AutoGen とのブリッジ@dcp-ai/google-a2a— Google Agent-to-Agent とのブリッジ@dcp-ai/w3c-did— W3C DID/VC とのブリッジ@dcp-ai/express— Express のミドルウェア@dcp-ai/openclaw— OpenClaw のプラグイン
@dcp-ai/express と @dcp-ai/openclaw は @dcp-ai/sdk ^2.0.0 に依存します。
2.0.0 - 2026-04-18¶
最初の公開パッケージのリリースです。npm(@dcp-ai/sdk、@dcp-ai/cli、@dcp-ai/wasm)、PyPI(dcp-ai)、crates.io(dcp-ai)に同時に公開しました。
追加¶
プロトコルスタック(DCP-01 から DCP-09)
- DCP-01 アイデンティティと人間とのバインディング — エージェントのアイデンティティ、オペレーターによる証明、鍵のバインディング
- DCP-02 意図の宣言とポリシーによるゲーティング — 宣言された意図、階層の強制、ポリシーの評価
- DCP-03 監査チェーンと透明性 — ハッシュで連鎖した監査エントリー、Merkle の証明、透明性ログ
- DCP-04 エージェント間通信 — 発見、ハンドシェイク、暗号化されたセッション
- DCP-05 エージェントのライフサイクル — 運用開始、バイタリティレポート、運用終了記録、4 つの終了モードを持つ状態機械
- DCP-06 デジタルな承継と継承 — デジタル遺言、承継セレモニー(計画的/強制/緊急)、選択的なメモリー移転マニフェスト
- DCP-07 紛争の解決と仲裁 — 型付きの紛争記録、3 段階のエスカレーション、M-of-N の仲裁パネル、判例バンドル、異議記録
- DCP-08 権利と義務の枠組み — エージェントの 4 つの権利(メモリーの完全性、尊厳ある移行、アイデンティティの一貫性、不変の記録)、義務の追跡、DCP-07 と結び付いた違反の報告
- DCP-09 個人の代理と委任 — 委任マンデート、認識しきい値、助言の宣言、プリンシパルミラー、二層のやり取りの記録。DCP-04 のハンドシェイクをマンデートの検証で拡張
暗号(4 階層: Routine / Standard / Elevated / Maximum)
- 耐量子の複合署名 —
pq_over_classicalバインディングによる Ed25519 + ML-DSA-65 - ハッシュベースの予備の署名としての SLH-DSA-192f(FIPS 205)
- 二重ハッシュの監査チェーン — 長期的な完全性のための SHA-256 + SHA3-256
- セッションバインディング — つなぎ合わせを防ぐ、すべての成果物の
session_nonce - bundle マニフェスト — 成果物ごとのハッシュ、副の Merkle ルート、PQ チェックポイントの追跡
- アルゴリズムのガバナンス — 自動応答のポリシーを伴う署名付きの勧告
- 鍵の回復 — Shamir Secret Sharing による M-of-N のソーシャルリカバリー
- 緊急失効 — 事前登録したパニックボタン式の失効トークン
- ブラインド化された RPR のモード — プライバシーを守る責任を負うプリンシパルの記録
- ドメイン分離 — すべての署名にコンテキストタグ
- 決定的な kid の導出 —
hex(SHA-256(alg || 0x00 || pk))[0:32] - ワイヤーフォーマットの選択肢 — JSON(既定)+ CBOR(省略可能、30〜40% 小さい)
SDK、インテグレーション、ツール
- 5 つの SDK — TypeScript、Python、Go、Rust、WASM
- 10 のインテグレーション — Express、FastAPI、LangChain、OpenAI、CrewAI、OpenClaw、W3C DID、Google A2A、Anthropic MCP、AutoGen(DCP-01..09 を対象)
- V2 の JSON Schema —
schemas/v2/の下の完全なスキーマ一式 - NIST の KAT のテストベクター — FIPS 203/204/205 への適合のための Known Answer Tests
- 相互運用性のテスト — SDK 間での bundle の検証
- Docker Compose のスタック — 検証、アンカー、透明性ログ、失効のサービス
- CI/CD のパイプライン — 適合性テスト、複数の SDK のビルド、公開のワークフロー
- プレイグラウンド — DCP-01..09 のモジュール化したタブを持ち、モバイルに対応した、ブラウザーでの bundle の作成と検証
- プロジェクトのテンプレート — Express、LangChain、OpenAI、CrewAI のスタータープロジェクト
- CLI —
dcp-initとdcp-aiのコマンドを持つ対話型の@dcp-ai/cli - サーバーの強化 — DCP-05..09 のエンドポイントに対する本番水準の認証とレート制限
ドキュメントと引用
- Zenodo の関連論文: doi.org/10.5281/zenodo.19040913
CITATION.cff— 機械で読める引用のメタデータ
変更¶
human_binding_recordの名前をresponsible_principal_record(RPR)に変更- 署名の形式を
{ alg, public_key_b64, sig_b64 }から{ composite_sig: { classical, pq, binding } }に変更 - bundle のエンベロープを平坦な
bundle_hashから構造化されたmanifestに変更 - 数値フィールドは整数のみ(署名済みペイロードでは浮動小数点数を禁止)
- 検証は検証者が決定権を持つ(ポリシー駆動)ものに変更
修正¶
sdk/pyの PQ プロバイダー: ML-DSA-65 のモジュールのインポートとpqc_verifyのシグネチャ(pk、sig、msgを分離)sdk/pyの PQ プロバイダー: SLH-DSA-192f のモジュールのインポートとpqc_verifyのシグネチャsdk/pyの PQ プロバイダー:pqc_verifyの戻り値を取得(pqcrypto.verifyは例外を投げるのではなく bool を返すため、常に True を返していた)sdk/pyの暗号:generate_keypairで Ed25519 の秘密鍵を base64 でエンコード- CI: 適合性、暗号、複数の SDK のテストの失敗
後方互換性¶
- V2 の検証者は、
allow_v1_bundles: true(既定)の場合に V1 の bundle を受け入れる - V1 の検証者は、明確なエラーメッセージとともに V2 の bundle を拒否する
リリース前のマイルストーン¶
以下の日付は、最初のパッケージのリリースより前の仕様の変遷を示します。これらの時点ではパッケージは公開していません。
- 2026-01-15 — Genesis の仕様を凍結(DCP-01、DCP-02、DCP-03)
- 2026-02-28 — V2.0 の規範仕様を確定(耐量子のハイブリッド暗号、4 階層のセキュリティモデル、DCP-04 の A2A)
- 2026-03-16 — Zenodo で論文のプレプリントを公開
- 2026-04-15 — DCP-05..09 の憲章的な枠組みを
mainにマージ - 2026-04-18 — v2.0.0 を npm、PyPI、crates.io でリリース