Trusted Match Protocol 仕様
実験的。 Trusted Match Protocol は実験的サーフェスとして AdCP 3.0 の一部です — 少なくとも 6 週間の予告をもって 3.x リリース間で変わることがあります。TMP を実装するセラーは
experimental_features に trusted_match.core を宣言しなければなりません(MUST)。完全なコントラクトについては 実験的ステータス を参照。このサーフェスのフィールドは 3.0.0 GA まで非推奨サイクルの対象になりません。Definitions
Message Types
すべての TMP メッセージタイプは、デシリアライゼーションのためにメッセージを識別するtype フィールドを含みます。ルーターとエージェントはこのフィールドを使って JSON ボディをパースする正しいスキーマを選択します。
ContextMatchRequest
パブリッシャー(ルーター経由)からバイヤーエージェントに送られます。コンテンツコンテキストを含みます。ユーザーアイデンティティを含んではなりません(MUST NOT)。ContextSignals
コンテンツ環境の事前計算された分類器出力。生のコンテンツ(会話テキスト、記事本文、URL)を含んではなりません(MUST NOT)。分類された出力のみ。パブリッシャーが分類器境界。
3 つのレベルのコンテンツ開示 — パブリッシャーはバイヤーが必要とするものとパブリッシャーが共有して快適なものに基づいて選ぶ:
artifact— 完全なコンテンツ(記事本文、トランスクリプト、会話フロー、プロダクトページ)。コンテンツ標準アーティファクトと同じスキーマ。バイヤーがコンテンツを直接評価する。契約上の保護がバイヤーができることを統治する。TEE デプロイが暗号学的検証を上に追加する。artifact_refs— バイヤーが独立して解決する公開参照(URL、EIDR ID、URL ハッシュ)。バイヤーが自分でクロールして分類できる公開アドレス可能なコンテンツに使う。context_signals— 分類された出力(トピック、センチメント、キーワード、summary)。パブリッシャーがコンテンツやその参照を共有せずにコンテンツを記述したいときに使う。
context_signals はベースライン — すべてのバイヤーエージェントがそれを扱わなければならない(MUST)。artifact_refs と artifact は漸進的な強化。artifact_refs を送るパブリッシャーは、参照を解決できないバイヤーのためのフォールバックとして context_signals も送るべき(SHOULD)。
LLM ベースのバイヤーエージェントは、context_signals.summary と context_signals.topics を最初に評価すべき(SHOULD)。これらのフィールドは、最小のトークンコスト(約 30 トークン)でほとんどの関連性決定に十分なシグナルを提供する。artifact_refs からの完全なコンテンツ解決や artifact 評価は、精度がコストを正当化する高価値のパッケージのために予約すべき(SHOULD)。バイヤーは artifact コンテンツと context_signals.summary を信頼できないパブリッシャー生成の入力として扱わなければならない(MUST)。
リクエストは任意の組み合わせを含められる。ニュースサイトは artifact_refs(URL)と context_signals(事前分類されたトピック)を送る。CTV アプリは artifact_refs(EIDR ID)のみを送る。AI アシスタントは、コンテンツを直接評価するバイヤーには artifact(会話)を、加えてフォールバックとして context_signals を送る。コンテンツや参照を共有したくないパブリッシャーは context_signals のみを送る。
Artifact Ref Type Conventions
バイヤーはartifact_refs 文字列をパターンでパースします。次の慣例は規範的です:
バイヤーは、リクエストを失敗させるのではなく、サポートしない ref タイプを無視すべき(SHOULD)。
Artifact
型付きコンテンツ参照。各アーティファクトは標準またはカスタムの識別子スキームを使ってコンテンツの一片を識別します。Geo
インプレッション機会の地理的コンテキスト。パブリッシャーが粒度を制御します。ContextMatchResponse
バイヤーエージェントが返します。一致したパッケージのオファーと任意のレスポンスレベルのターゲティングシグナルを含みます。Offer
単一のパッケージに対するバイヤーの応答。OfferPrice
Signals
アドサーバー通過用のレスポンスレベルのターゲティングシグナル。KeyValuePair
IdentityMatchRequest
パブリッシャー(ルーター経由)からバイヤーエージェントに送られます。セラーエージェント URL、1 つ以上の不透明なアイデンティティトークン、任意のパッケージ ID リストを含みます。ページコンテキストを含んではなりません(MUST NOT)。identities の各エントリは {user_token, uid_type, attestation?} トリプルです:
IdentityMatchResponse
バイヤーエージェントが返します。サーブウィンドウスロットルを伴う適格なパッケージ ID のリスト。TmpxMacro
レスポンスは適格なパッケージ ID、サーブウィンドウスロットル、プロバイダーごとの TMPX 形状(ルーターマージ後の
tmpx_providers、またはプロバイダーごとのレベルでの tmpx_macros)を含みます。慣例により、プロバイダー→ルーターのペイロードは tmpx_macros を投入し tmpx_providers を欠如させる。ルーター→パブリッシャーのペイロードは tmpx_providers(各プロバイダーの tmpx_macros を収集して構築)を投入する。ルーターレスポンスはルートに tmpx_macros を運んではならない(MUST NOT) — 上流プロバイダーのルート配列を tmpx_providers と並んで漏らすと、パブリッシャーにどれを読むべきかのスキーマシグナルを与えず、同じ値を 1 つのスロットに二重発火し、マップが保護するために存在するプロバイダーごとの会計を破損するリスクがある。スキーマはこれを強制できない(同じスキーマが両方のホップに提供される)のでルーター適合性不変条件として存在する。ルーターはアウトバウンドレスポンスから tmpx_macros を落とさなければならない(MUST)。各 TMPX 値は、クリエイティブトラッキング URL を通じてバイヤーのインプレッションピクセルに流れる HPKE 暗号化された露出トークンで、ユーザーアイデンティティをパブリッシャーに露出せずにリアルタイムのユーザーごとのフリークエンシー状態更新を可能にする。バイヤーは持っている任意のアイデンティティシグナル(フリークエンシーキャップ、オーディエンスメンバーシップ、購入履歴)から適格性を計算し、通過するパッケージのみを返す。パブリッシャーはパッケージがなぜ除外されたかを知る必要はない — どのパッケージが適格かだけ。
TMPX マクロトラフィッキング。 マクロ名は運用セットアップの一部であり、プロトコルが合成する識別子ではない。各アイデンティティプロバイダーは、そのプロバイダー登録エントリの tmpx_macros に安定したプロバイダー名前空間化されたマクロ名を登録する(例: Pinnacle は ["PIN_TMPX_1", "PIN_TMPX_2"] を、Nova は ["NOVA_TMPX_1"] を登録)。パブリッシャーはそれらの正確な名前をそのアドサーバー(GAM キー値、VAST URL マクロ、DOOH play-log フィールド)で設定する。レスポンスが到着すると、パブリッシャーは各プロバイダーの macros[].value を一致する macros[].name スロットに発火する — コントラクトは「この正確な文字列をこの正確なマクロに代入する」。順序付けられたマルチチャンクサポートにより単一の TMPX が 1 つのマクロスロットを超えられる(v1 ではプロバイダーごとに 2 チャンクに上限、shape change なしに上げられる MAY)。実行時に provider_id からマクロ名を導出することは、GAM/アドサーバーラインアイテムが実行時合成文字列ではなく登録された名前に対して事前に設定されるため、このトラフィッキングモデルを壊す。
tmpx_providers は、ファンアウトが複数のアイデンティティプロバイダーに到達したときルーターがアトリビューションを保つよう、マクロ/値ペアを provider_id でキー付けする。レガシー tmpx フィールドは、移行していないコンシューマーのため 3.x を通じてサポートされたまま。両方のフィールドが存在するとき、tmpx_providers が権威的で、単数フィールドは移行的な便宜としてのみ 1 つのプロバイダーの最初のスロット値を反映すべき(SHOULD)。
serve_window_sec フィールドは パッケージごとのシングルショット fcap であり、ルーターキャッシュ TTL ではない。バイヤーはこう言っている: 「各適格パッケージにユーザーへ 1 インプレッションを提供した後、それらのパッケージから再び提供する前に私に再クエリせよ。」ルーターは内部の重複排除/コスト節約ウィンドウのためにレスポンスをキャッシュしてもよい(MAY)が、パブリッシャー側の拘束コントラクトは「ウィンドウごとの適格パッケージごとに 1 インプレッション」。マルチインプレッションフリークエンシーキャップ(キャンペーンごとに 1 日 5、広告主ごとに 1 か月 100 など)はバイヤーのインプレッショントラッカーに存在し、serve_window_sec にかかわらず境界でキャップ発火イベントとして IdentityMatch サービスにサーフェスする。
パブリッシャーは適格性リストを入力として割り当てルール(競合分離、ポッド構成)を強制する。これはポッド固有またはバッチ固有のプロトコルセマンティクスの必要を除去する — パブリッシャーは、one-impression-per-package コントラクトを尊重しながら、サーブウィンドウ中に存在する任意のプレースメント(CTV 広告ポッド、20 スロットの web ページ、単一のプレロール)にわたって割り当てる。
Conformance invariants for IdentityMatch eligibility
準拠する IdentityMatch サービスは、各package_id ∈ request.package_ids について、次の すべて が成立する場合かつその場合に限りパッケージが eligible_package_ids に含まれるように eligible_package_ids を計算しなければなりません(MUST):
- オーディエンス適格性。 パッケージがオーディエンス要件を持たないか、または
aがパッケージの必要オーディエンスセットにありかつaが少なくとも 1 つのアイデンティティi ∈ request.identitiesのオーディエンスメンバーシップにあるようなオーディエンス識別子aが少なくとも 1 つ存在する(ユーザーの解決されたアイデンティティにわたる union がパッケージの必要オーディエンスと交差する)。 - フリークエンシーキャップ適格性。 任意のアイデンティティ
i ∈ request.identitiesに対してパッケージに(identity, package)キャップ状態エントリが存在しない。キャップ状態エントリは、バイヤーのインプレッショントラッカーがインプレッションがキャップを使い果たしたと判断したときに書き込まれ、有効期限タイムスタンプを運ぶ。エントリはそのタイムスタンプまで「存在」する。プロトコルは、インプレッショントラッカーがどうインプレッションをカウントし、ウィンドウを評価し、いつキャップが発火するかを決めるかを制約しない — 境界コントラクト(キャップ発火エントリがキャップ状態ストアに流れ込み、IdentityMatch サービスがクエリ時に存在を確認)のみ。境界コントラクトについては フリークエンシーキャップデータフロー を参照。 - アクティブ状態。 inactive とマークされたパッケージまたはポリシーは absent であるかのように扱わなければならない(MUST)。
- オーディエンス鮮度。 バイヤーのオーディエンスパイプラインが鮮度期限を公開し現在時刻がそれを過ぎている場合、そのオーディエンスメンバーシップエントリは (1) に寄与してはならない(MUST NOT)。
- 年齢適格性(実験的 —
trusted_match.verified_identityが有効なときのみ適用)。パッケージが年齢ポリシーを要求しないか、または何らかのアイデンティティi ∈ request.identitiesが、(パッケージの必要年齢ポリシー, request geo)から解決されたしきい値以上の年齢クレームを持つ 検証済みattestation(Verified Identity Attestation の適合性ルール準拠)を運ぶ。未検証または欠如のアテステーションはこの条項を満たさない。機能が有効でないとき、この条項は自明に真なので、コア適合性は変わらない。
Consent
identity match のプライバシー同意シグナル。パブリッシャーは、規制された管轄区域(EU/EEA、カリフォルニアなど)で動作するとき同意情報を含めなければなりません(MUST)。バイヤーは、適用法が要求するとき、同意情報なしにユーザートークンを処理してはなりません(MUST NOT)。Verified Identity Attestation
実験的 —experimental_features に trusted_match.verified_identity を宣言(trusted_match.core とは別、そのためバイヤーがサポートを独立に検出できる)。パブリッシャー — または relying party として動作するネットワーク/発行者 — が、バイヤーがアサーションを信頼するのではなくクレームを暗号学的に検証するよう、ユーザー について の 検証可能な 証明(人格証明および/または年齢)を運べるようにする。発行者非依存: World ID が最初のスキーム。mDL / VC スタイルの発行者は同じ形状を使う。設計理由: specs/tmp-verified-identity-attestation.md。
これは、そうでなければ additionalProperties: false である identity-match-request.json を拡大します。拡大は意図的: アテステーションはプライバシー境界の アイデンティティ 側の証明であり — ページコンテキストではない — なので厳格なスキーマが保護する境界を破らない。
Topologies
Attestation
各identities[] エントリの任意オブジェクト。
SealedCredential
トップレベルのsealed_credentials[] のエントリ。
Conformance invariants (verified attestation)
アテステーションを受け入れる受信者は次をしなければなりません(MUST):- 信頼の前に検証。 受け入れるすべての
schemeについて証明を検証する。検証に失敗するアテステーション — またはsignal_binding、relying_party_id来歴、expires_at— は、asserted-true クレームとしてではなく absent(アテステーションなし)として扱わなければならない(MUST)。 - 黙った格上げなし。 未検証または検証不能なアテステーションを決して
trueとして扱わない。 - relying_party_id 来歴。 信頼する前に、アテステーションの
relying_party_idがトラフィックを主張するエンティティに属することを確認する。所有者のbrand.jsonidentity_relying_parties[]が v1 のディスカバリーサーフェスだが、HTTPS 上で自己公開される — 権威あるルートは発行者自身の relying-party レジストリ(例: World ID のオンチェーンレジストリ)で、それに対してbrand.jsonはクロスチェック。受信者は、発行者側のアンカーなしに、何らかのbrand.jsonがリストするからという理由だけでrelying_party_idを信頼してはならない(MUST NOT)。双方向の発行者メタデータクロスチェックは追跡されたオープン項目。 - 封印された認証情報。 受信者が鍵を持つ
audience_kidのsealed_credentials[]エントリのみを復号する。残りは無視。 - 有界リソース。 DoS を防ぐためアテステーションと封印された認証情報の数とサイズを有界化する。
signal_binding 鮮度ウィンドウと nullifier 再利用追跡 — 両方とも v1 では検証者に委ねられる(鮮度ポリシーは WG オープン) — なしでは、このサーフェスはせいぜい日次エポックのリプレイ耐性(request_id 重複排除経由)を提供する。受信者は signal_binding を新鮮で受信者確認可能な値にバインドし nullifier 再利用を追跡すべきで(SHOULD)、そうするまでアテステーションをインプレッションごとのライブネスシグナルとして過度に信頼してはならない(MUST NOT)。
Router handling of sealed_credentials[]
ルーターは各 sealed_credentials[] エントリを、その audience_kid を所有するプロバイダーにのみ転送しなければなりません(route-by-audience、ブロードキャストでない)(MUST)。改ざん証拠とキャッシュ分割のルールは Identity Match signed fields と Caching で正準的に定義される: sealed_credentials はプロバイダーごとの再署名の正準バイトに折り込まれる(そのため注入または交換された blob がリクエスト署名を壊す)、sealed_credentials_hash は重複排除キャッシュキーの一部(そのためネットワーク認証情報の変更が古いレスポンスを提供するのではなくキャッシュを再分割する)。同じ正準アイデンティティバイトは既に任意のアイデンティティごとの attestation をカバーする。
Age as eligibility
検証済み年齢クレーム(age_over_N)は eligible_package_ids に解決される — 平文の年齢や生年月日として 決して 運ばれない。検証する当事者は (required age policy, geo) → required threshold claim をマップし、アテステーションが必要しきい値以上のクレームを運ぶときのみパッケージを含める。管轄区域 → しきい値のテーブルは AdCP Policy Registry で維持される(パッケージは required_policies 経由で年齢ポリシーを要求する)。sub-country(例: 米国州)解決は、Identity Match country フィールドが粗く転送前に剥がされるため、より細かい geo が利用可能な場所で起こる。
Error Response
リクエストが処理できないときプロバイダーまたはルーターが返します。空の結果とは別 — 空のoffers 配列や空の eligible_package_ids リストは、エラーではなく一致なしを意味する有効なレスポンス。
ルーターは、そのリクエストのマージされたレスポンスからエラーを返すプロバイダーを除外すべき(SHOULD)。ルーターはプロバイダーごとのエラー率を追跡し、持続的なエラーを持つプロバイダーを先制的にスキップしてもよい(MAY)。
Provider Registration
TMP プロバイダーはパブリッシャー設定を通じてルーターに登録されます。パブリッシャーは、各プロバイダーのエンドポイントとサポートするケイパビリティとともに、ルーターがどのプロバイダーを呼ぶべきかを指定します。これは運用上の関係です — パブリッシャーはプロバイダーがその広告決定パスでコードを実行することを信頼します。 標準の登録パスは 静的設定 — パブリッシャーが Prebid モジュール設定、ルーター YAML、または同等のサーフェス固有の設定でプロバイダーを宣言する。動的登録(API 駆動、データベース裏付け)は、多くのプロバイダーを管理するかランタイム更新が必要なパブリッシャーのための等しく有効なバリアント。両アプローチは同じプロバイダー登録スキーマ(/schemas/trusted-match/provider-registration.json)を使う。
context_match または identity_match の少なくとも一方が true でなければなりません — どちらの操作も扱わないプロバイダーは無効です。identity_match が true のとき、countries と uid_types は 必須 です — ルーターはそれらなしに国分割アイデンティティルーティングを実行できません。スキーマは両方の制約を強制します。
プロバイダーは context_match と identity_match の任意の組み合わせをサポートしてもよい(MAY)。context_match のみをサポートするプロバイダーは純粋なエンリッチメントまたはコンテキストターゲティングプロバイダー。identity_match のみをサポートするプロバイダーはフリークエンシーキャッピングプロバイダー — パブリッシャーはメディアバイのターゲティングルールからコンテキストをローカルで評価し、アイデンティティチェックのためだけにバイヤーを呼ぶ。
Provider lifecycle
プロバイダーは 3 つのライフサイクル状態を持ちます:- Active: プロバイダーが通常どおりリクエストを受け取る。
- Draining: プロバイダーが新しいリクエストの受け取りを停止する。飛行中のリクエストは通常どおり完了する。プロバイダーを保守のためオフラインにするとき使う — ルーターはこのプロバイダーへの新しいファンアウトを開始せずに現在の作業を終える。
- Inactive: プロバイダーが完全にスキップされる。設定を削除せずにプロバイダーを無効化するとき使う。
Provider registration security
エンドポイント URL 検証(SSRF)。 静的設定と動的登録の両方が、プロバイダーendpoint URL を正準の Webhook URL 検証(SSRF) ルールに対して検証しなければなりません(MUST) — 本番では HTTPS のみ、予約された IPv4 と IPv6 範囲を拒否(::ffff:0:0/96 の IPv4 マップバイパスと 169.254.169.254 / fd00:ec2::254 クラウドメタデータアドレスを含む)、リダイレクトなし。ルーターがすべてのリクエストでプロバイダーを呼ぶため、DNS リバインディングが主要なリスク: ルーターは、検証を通過した IP に TCP 接続をピン留めするか、リクエストボディを送る前にソケットのハンドシェイク後のピアアドレスを再検証するかのいずれかをしなければならない(MUST)。ピン留めなしに DNS を再解決するのは不十分。
動的登録認証。 動的登録 API は特権的なサーフェス。未認証の登録は攻撃者がパブリッシャートラフィックを任意の HTTPS エンドポイントに向けることを許す。動的登録を公開するルーターは呼び出し元を認証しなければならず(MUST)(mTLS または短命の OAuth 2.0 トークン。静的 API キーは IP 許可リストとともにのみ)、変更のエージェントごとのレート制限と登録ストーム悪用を有界化するためパブリッシャーごとの総登録プロバイダー数の上限を適用すべき(SHOULD)。
ルーター対プロバイダー認証。 Request Authentication の既存の「デプロイ固有(mTLS、API キーなど)」の言葉がメカニズムを設定する。最低ラインは、本番プロバイダーが匿名呼び出しを受け入れてはならない(MUST NOT)こと。静的 bearer トークンは IP 許可リストとともにのみ使ってもよい(MAY)。
/health エンドポイント。 ルーターの生存性のためにプロバイダーが公開することが推奨される /health エンドポイントは未認証でもよい(MAY)が、レスポンスは内部状態を漏らしてはならない(MUST NOT)。プロバイダーは準備完了のとき 200 をボディ {"status": "ok"} とともに、準備未完了のとき 503 を返すべき(SHOULD)。他のステータスコードはバグ。プロバイダーは内部サブシステムによってステータスコードやレスポンスボディを区別してはならない(MUST NOT)(例えば、データベースがダウンしているときとアイデンティティキャッシュがダウンしているときの distinct なコードは、外部プロービングを内部トポロジーにマップするサイドチャネル)。バージョン文字列、ビルドハッシュ、内部ホスト名、依存関係ステータスはボディに現れてはならない(MUST NOT)。DoS 増幅器にならないようエンドポイントをレート制限(推奨: ソース IP ごとに 1 req/秒)する。
Product Integration
パブリッシャーはtrusted_match フィールド経由でそのプロダクトに TMP サポートを宣言します。バイヤーは get_products でこれを見て、どの TMP ケイパビリティが利用可能かを知ります。
ProviderEntry
Package Sync
パッケージメタデータは、メディアバイ作成時、およびメディアバイが実質的に変わるたびに、セラーエージェントから TMP プロバイダーに同期されます。プロバイダーはプレースメントごとにAvailablePackage セットをキャッシュしリクエスト時に使う — context_match_request や identity_match_request を通じてパッケージメタデータは流れない。同期トランスポート、認証、バッチエラー形状はデプロイ固有。このセクションはペイロードコントラクトと各参加者が継承する義務を定義する。
AvailablePackage の seller_agent は実験的 trusted_match.core サーフェスの下で必須です。既存のデプロイで TMP を実行するセラーは、それを投入するよう同期ペイロードを更新しなければなりません — 3.x-to-3.x 進化ポリシーについては 実験的機能コントラクト を参照。AvailablePackage
SellerAgentRef
Seller Agent Attribution
TMP プロバイダーは多くのセラーエージェントからのパッケージを多くのパブリッシャーに対してキャッシュします。seller_agent フィールドは各キャッシュされた AvailablePackage にその来歴を明示的にし、プロバイダー — メディアバイストアへのアクセスを持たない — が、帯域外ルックアップなしにオファーを帰属させ、セラーごとの可観測性を適用し、紛争を解決できるようにします。
AdCP の正準セラーアイデンティティは、プロパティパブリッシャーの adagents.json authorized_agents[].url エントリで宣言されたエージェント URL です。TMP は並行する識別子空間を導入するのではなくその URL を直接再利用します。SellerAgentRef の id スロットは将来のレジストリ割り当ての不透明な識別子のために予約され、今日は使われません。
配置理由。 context_match_request と identity_match_request の両方が seller_agent_url を運びます。それは、受信エージェントが尋ねるセラーに登録したアクティブなパッケージセットを解決するのに使うキー: コンテキストパスのプロバイダー、アイデンティティパスのバイヤーエージェント。package_ids が省略されたとき、評価はそのセラーの完全なアクティブセットに対して実行される。受信者がパッケージを同期していない seller_agent_url は、別のセラーのセットへのフォールバックではなく空の結果を生成しなければならない(MUST)。
seller_agent は、アトリビューションのためキャッシュされた AvailablePackage(同期時)にも存在する — そのバインディングがどのセラーがパッケージを所有するかの真実の源泉で、下のオファーエコーがそれから読む。2 つは異なる仕事を運ぶ: リクエスト側の seller_agent_url はどのセラーのセットを評価するかを選択し、パッケージ側の seller_agent は個々のパッケージを帰属させる。同期時はプロバイダーが最初にパッケージについて学ぶとき。そのバインディングは一度確立され後続のすべての評価で再利用される。
seller_agent_url は Package set decorrelation 保証と相互作用しません。その保証は、ユーザーごとに変わるデータ — 主に package_ids、その構成は現在のプレースメントと独立でなければならない — を制約します。seller_agent_url は尋ねるセラーを識別する単一の安定した値で、特定のプレースメントのすべてのユーザーで同一でありユーザーアイデンティティを運ばないので、コンテキストとアイデンティティのリクエストが相関されうるユーザーごとのシグナルを追加しない。これは受信者側のアクティブセットスコーピングで、ユーザーごとのフィルターではない。
オファーエコー。 seller_agent は、メディアバイストアに再結合せずにワンホップアトリビューションを望むパブリッシャー側のログパイプラインのため、キャッシュされたパッケージからのエコーとして offer.json に現れてもよい(MAY)。エコーは非権威的 — キャッシュされた AvailablePackage バインディングが真実の源泉。プロバイダーとルーターは、ログ、転送、または下流へのオファー発出の前に、不一致のエコーをキャッシュされたバインディングで上書きしなければならず(MUST)、課金、レポート、紛争解決に消費される任意のフィールドでエコー値を使ってはならない(MUST NOT)。不一致は異常検出のため seller_agent_echo_mismatch メトリクスにカウントすべき(SHOULD)。ルーターはプロバイダーが省略したときマージで seller_agent をスタンプしてもよい(MAY)。
Sync-Time Validation
プロバイダーは同期時にseller_agent.agent_url をプロパティパブリッシャーの adagents.json に対して検証すべきです(SHOULD):
- パッケージが提供しうる各プロパティについて、プロパティドメインの
/.well-known/adagents.jsonをフェッチする。ファイルがauthoritative_locationポインターを含む場合、同一スキームの HTTPS URL への最大 1 ホップでそれをたどる。それ以上チェーンしない。初期フェッチとauthoritative_locationホップの両方が Webhook URL 検証(SSRF) ルールを適用しなければならない(MUST) — HTTPS のみ、予約された IPv4 と IPv6 範囲を拒否(::ffff:0:0/96IPv4 マップバイパスと169.254.169.254/fd00:ec2::254クラウドメタデータアドレスを含む)、透過的リダイレクトなし、TCP 接続を検証された IP にピン留め。Provider registration security で参照されるインバウンドフェッチルールは、このアウトバウンドフェッチにも等しく適用される。 seller_agent.agent_urlがauthorized_agents[].urlに現れ、そのエントリの任意のproperty_ids、collections、placement_ids、placement_tags、countries、effective_from、effective_until制約がパッケージのスコープを許すことを確認する。URL 比較は AdCP URL 正準化ルール を使う — マッチング前に両方の値を正準化する、決してバイト等価でない。https://スキームを使わないseller_agent.agent_url値をseller_not_authorizedで拒否する。非 HTTPS セラー URL はトランスポート完全性保証を持たず認可キーとして信頼できない。- 不一致で、その
AvailablePackageの同期操作をcode: seller_not_authorizedを使うerrorレスポンスで拒否する。同じ同期バッチの他のパッケージは影響を受けない。同期エラーの正確なワイヤー形状はデプロイ固有。codeが機械可読な理由。
seller_not_authorized 拒否をパブリッシャー運用にサーフェスすべき(SHOULD) — 繰り返しの失敗は通常、パブリッシャーの adagents.json とセラーの同期パイプラインが分岐したことを示す。認可の effective_until が過ぎるかセラーが authorized_agents から削除されるとき、プロバイダーは、再同期・再検証されるまで、そのセラーからの以前キャッシュされたパッケージをリクエスト時に unknown_package として扱わなければならない(MUST)。
フェッチ失敗。 検証が完了できないとき(フェッチエラー、タイムアウト、証明書失敗、不正な形式のファイル)、プロバイダーは、検証されていないバインディングをキャッシュするのではなく seller_not_authorized で同期を拒否すべき(SHOULD)。fail-open するプロバイダーは、検証されていないウィンドウを 5 分のキャッシュ TTL に有界化し、次の機会に再検証しなければならない(MUST)。一度も検証に成功していないバインディングは、そのウィンドウを過ぎてキャッシュされたままであってはならない(MUST NOT)。
事前アテスト済み関係のバイパス。 プロバイダーは、同じ agent_url → authorized_agents[].url バインディングを帯域外オンボーディングプロセス(例: パブリッシャーのアテステーションを運ぶ相互認証されたプロバイダー-セラー登録)を通じて検証できるときのみ adagents.json チェックをスキップしてもよく(MAY)、パブリッシャーがオンボーディングをゲートできるよう、その適合性自己レポートに強制モード(enforcing / advisory)を公開すべき(SHOULD)。このエスケープハッチは trusted_match.core v1 で許可され、最初の非実験的 TMP リリースで削除され、その時点で検証は MUST になる。
Participant Responsibilities
What This Is Not
- ユーザーごとのフィルターではない。
seller_agent_urlは受信者が評価するどのセラーの登録されたアクティブセットかを選択する — プレースメントのすべてのユーザーで同じ値でユーザーアイデンティティを運ばない。パブリッシャー、ルーター、プロバイダーはそれをユーザーごとまたはリクエストごとのフィルターとして、またはリクエストを再ルーティングするために使ってはならない(MUST NOT)。そうすることは Package set decorrelation が防ぐために存在するユーザーごとの変動を再導入する。パッケージ側のseller_agentアトリビューションも同様にリクエストをスコープまたはフィルターするのに使ってはならない(MUST NOT) — オファーアトリビューションのためだけに存在する。 - sellers.json ブリッジではない。 IAB sellers.json
seller_idと TAG-ID は distinct な財務監査アイデンティティ空間に提供する。それらはadagents.jsoncontactに残る — TMP はそれらを複製しない。 - 暗号学的アテステーションではない。 バインディングは adagents.json 経由で HTTPS 上でパブリッシャーアテストされる。署名付き TMP セラークレームは将来の強化で、破壊的変更なしに予約された
idスロットまたはextフィールドを通じてSellerAgentRefに重ねられる。将来のリリースがagent_urlとidの両方を投入するとき、agent_urlが権威的のままでidは助言的 — 2 つの間の不一致は、URL の adagents.json バインディングが提供するものを超えて信頼を格上げするのに使ってはならない(MUST NOT)。
Privacy Requirements
次の要件は RFC 2119 キーワード(MUST、SHOULD、MAY)を使います。Structural separation
- Context Match リクエストはユーザーアイデンティティデータ(ユーザートークン、デバイス ID、IP アドレス、セッショントークン、特定のユーザーを識別しうる任意のデータ)を含んではならない(MUST NOT)。
- Identity Match リクエストはページコンテキストデータ(URL、コンテンツハッシュ、トピック ID、コンテンツシグナル、ユーザーが何を見ているかを識別しうる任意のデータ)を含んではならない(MUST NOT)。
- TMP ルーターは、共有状態のない構造的に分離されたコードパスで Context Match と Identity Match を処理しなければならない(MUST)。
- Context Match と Identity Match のリクエスト ID は相関または互いから導出可能であってはならない(MUST NOT)。
Package set decorrelation
- Context Match はユーザーアイデンティティやオーディエンスでフィルターしてはならない(MUST NOT)。プロバイダーはプレースメントの同期されたパッケージセット — すべてのユーザーで同じパッケージ — を評価する。リクエストごとのパッケージリストは送られないので、パブリッシャーはパッケージフィルタリングを通じて誤ってアイデンティティを漏らせない。
- パブリッシャーは Identity Match から
package_idsを省略し、バイヤーにseller_agent_urlに登録した完全なアクティブセットに対して評価させるべき(SHOULD)。package_idsが提供されるとき、その構成は現在のプレースメントと統計的に独立でなければならない(MUST) — ページ固有のサブセットのみを送ることは、バイヤーがパッケージセットを比較して Identity Match を Context Match と相関させることを許す。2 つの許容モード:- All-active。 このバイヤーがこのパブリッシャーに持つすべてのアクティブパッケージを含める。
- Fuzzed。 アクティブなパッケージのランダムサンプル、任意で合成の存在しない ID でパディング、現在のプレースメントに依存しない分布から抽出。下の silent-drop ルールが合成 ID パディングを安全にする — 未知の ID はレスポンス形状に影響せずレジストリメンバーシップを漏らせない。
seller_agent_urlとpackage_idsの両方が存在するとき、バイヤーは登録されたアクティブセットとpackage_idsの交差に対して評価する。package_idsの未知の ID は、レスポンスがレジストリメンバーシップをパブリッシャーに漏らさないよう、黙って無視されなければならない(MUST)(エラーサーフェスしない)。- バイヤーごとのすべてのアクティブパッケージ ID のキャッシュされたリストを維持するパブリッシャーは、多層防御としてすべての Identity Match リクエストで完全なセットを送ってもよい(MAY)が、
seller_agent_urlからのバイヤー側解決が主要なメカニズム。 - パブリッシャーは、両方のレスポンスが到着した後、context match オファーと identity match 適格性の交差をローカルで実行する。
Temporal decorrelation
- パブリッシャーは Context Match と Identity Match リクエスト間にランダムな遅延を導入すべき(SHOULD)。推奨: 100-2000ms、一様分布。
- パブリッシャーは Context Match と Identity Match の順序もランダム化すべき(SHOULD): 各機会は Context Match が先に送られるか Identity Match が先に送られるかのほぼ等しい確率を持つべき。固定順序 — 例えば Identity Match が常に Context Match の後 — は、遅延がランダム化されても順序を通じてペアリングを漏らす。
- パブリッシャーは複数のページビューにわたって Identity Match リクエストをバッチしてもよい(MAY)。
- パブリッシャーは Context Match と Identity Match を異なるネットワークパス経由でルーティングしてもよい(MAY)。
TEE attestation
- TMP ルーターは、利用可能なとき、デプロイされたバイナリが公開されたソースに一致することを証明する TEE アテステーションを提供すべき(SHOULD)。
- アテステーションドキュメントは、リクエストに応じてパブリッシャーと監査者に利用可能であるべき(SHOULD)。
- アテステーションは、サービスコードの完全性と分離を確認する測定を含むべき(SHOULD)。
Consent handling
- Identity Match リクエストから
consentが省略されたとき、バイヤーはこれを「同意不要」ではなく「同意ステータス不明」として扱わなければならない(MUST)。 - 同意が要求される管轄区域のバイヤーは、
consentを省略する Identity Match リクエストを、同意を仮定するのではなく拒否しなければならない(MUST)。
User token requirements
- ユーザートークンはバイヤーエージェントにとって不透明でなければならない(MUST)。トークンはアイデンティティプロバイダー(ID5、LiveRamp、UID2)から発生するか、パブリッシャー生成であってよい。
- ユーザートークンは PII を含んではならず、バイヤーエージェントによって PII に逆変換可能であってはならない(MUST NOT)。
Request Authentication
TMP リクエストは、リクエストが認可されたルーターから発生したことを証明する署名を運びます。これは、認可されていない当事者がプロバイダーに偽造リクエストを送ってターゲティングロジックをプローブし、スポンサーコンテンツを抽出し、フリークエンシー状態を操作するのを防ぎます。Signing model
ルーターは Ed25519 を使ってすべてのリクエストに署名します。Context Match と Identity Match の両リクエストが署名されますが、その異なるコンテンツとキャッシュ特性を反映する異なる署名フィールドで。 署名はリクエストを特定のプロバイダーにバインドします。ルーターは、ルーターのプロバイダー登録からのプロバイダーのエンドポイント URL を使って、ファンアウトターゲットごとに別個の署名に署名します。プロバイダーは、署名されたprovider_endpoint_url が自身のアドバタイズされたエンドポイントに一致することを検証し、そうでなければリクエストを拒否しなければなりません(MUST)。これは、キャプチャされた署名がエポック内でレジストリの異なるプロバイダーに対してリプレイされるのを防ぎます。
署名は、尋ねるセラーのエージェント URL である seller_agent_url にもバインドします。seller_agent_url は受信者がどのセラーの登録されたアクティブパッケージセットに対して評価するか(Seller Agent Attribution を参照)を選択し、受信者が検証のためパブリッシャーの署名鍵を解決するのに使うルックアップキーです。それを署名バイトに含めることは、キャプチャされた署名が別のセラーのアイデンティティの下でリプレイされて別のセラーのオファーやアクティブパッケージセットを読むのを防ぎます。
日次エポックがリプレイ保護を提供します — キャプチャされた署名はせいぜい約 48 時間(現在 + 前のエポックが検証者に受け入れられる)有効です。
Signature envelope
署名は JSON ボディと並んで HTTP ヘッダー経由で送信されます。Context Match signed fields
この順序で連結、UTF-8、改行区切り:package_ids がリクエストから欠如するとき、署名は署名されたペイロードのそのフィールドに空文字列を使わなければならない(MUST)。
署名フィールドはセラーごとプレースメントごとプロバイダーごとに静的なので、同じ署名は 24 時間エポック内の同じ (seller_agent_url, placement_id, provider_endpoint_url) トリプルへのすべてのリクエストにキャッシュして再利用できます。キャッシュキーは seller_agent_url と provider_endpoint_url を含まなければならない(MUST) — セラーやプロバイダーをまたいで署名を再利用することはバインディングに違反し検証に失敗する。
Identity Match signed fields
署名された入力は、次の正準オブジェクトの RFC 8785 JCS シリアライゼーションの hex エンコードされた SHA-256 です。JCS を使うことでデリミタ注入リスクが除去されます — 生のtcf_consent / gpp / us_privacy / package_id 値は任意のバイトを含みうるが、JCS の JSON 文字列エスケープが任意のフレーミングバイトを無害にする。
正準
identities バイト: バイト正確なマッチ(case folding なし、trimming なし)を使って (uid_type, user_token) で重複排除 — これは重複トークンのみを折り畳む — エントリを uid_type(UTF-8 バイト順)、次に user_token(UTF-8 バイト順)でソートし、結果の 完全なアイデンティティオブジェクト の配列を RFC 8785 JCS としてシリアライズ。各オブジェクトは、任意の attestation を含め 完全にシリアライズされる — そのため署名がアテステーションをカバーし、剥がされた、交換された、または注入されたアイデンティティごとのアテステーションが署名検証を壊す((uid_type, user_token) の重複排除キーは重複トークンを折り畳むためで、attestation がハッシュから除外されるという声明ではない)。UTF-8 バイトを SHA-256 し、署名された入力には hex エンコード、キャッシュキーには生バイトを使う(両方の慣例が同じプリイメージをハッシュする)。
正準 sealed_credentials バイト(実験的、trusted_match.verified_identity): エントリを audience_kid(UTF-8 バイト順)でソートし、結果の配列を RFC 8785 JCS としてシリアライズ、UTF-8 バイトを SHA-256。リクエストが sealed_credentials を運ばないとき、sealed_credentials_hash は null。sealed_credentials が署名された入力の一部なので、注入または交換された封印 blob が署名検証を壊す。sealed_credentials_hash が重複排除キャッシュキーの一部(Caching を参照)なので、ネットワーク認証情報の変更がキャッシュを再分割し古い適格性が提供されない。ルーターは route-by-audience_kid フィルタリングの後、各プロバイダーの転送されたセットに対して再署名する。
ルーターは転送前にプロバイダーごとに identities をフィルターします(Identity Match ファンアウト を参照)。署名は各プロバイダーのフィルターされた identities セットに対して計算される — ルーターはアウトバウンド転送ごとに再署名する。同じフィルターされた identities_hash 値がキャッシュキー(Caching を参照)で使われるので、各プロバイダーは実際に受け取ったサブセットでキー付けされた独自のキャッシュパーティションを持つ。
Identity Match 署名は request_id と identities_hash を含むので、リクエストごとに一意でキャッシュできない。これは意図的 — Identity Match レスポンスはバイヤー側のフリークエンシー状態に影響し冪等でなければならない。バイヤーは日次エポックウィンドウ内で request_id によって Identity Match リクエストを重複排除しなければならない(MUST)。繰り返された request_id は、フリークエンシー状態を更新せずに同じレスポンスを返さなければならない(MUST)。バイヤーは生の識別子を保持するのではなく hash(request_id) で重複排除すべき(SHOULD)。
Signature verification
ルーターは、署名しファンアウトする前に、パブリッシャーからのインバウンドリクエストを認証しなければなりません(MUST)。パブリッシャー対ルーター認証のメカニズムはデプロイ固有(mTLS、API キーなど)で TMP 署名のスコープ外だが、強制されなければならない(MUST)。これは、侵害されたパブリッシャー側のコンポーネントが未認証リクエストをルーターの署名を通じてロンダリングするのを防ぎます。 ルーターはファンアウトする前にリクエストに署名します。プロバイダーは、プロパティレジストリから得たパブリッシャーの公開鍵を使って署名を検証します。これは、リクエストが認可されたルーターから発生したことを証明します — プロバイダーのターゲティングロジックをプローブするサードパーティではなく。プロバイダーは、すべてのリクエストを検証するのではなくサンプル検証すべき(SHOULD) — Ed25519 検証はリクエストごとに約 30μs 追加し、完全なパイプラインに比べれば小さいがボリュームでは積み重なる。5% のサンプルレートが、無視できるオーバーヘッドを追加しながら数秒以内に不正なパブリッシャーを検出する。 検証失敗で、プロバイダーは設定可能な期間(推奨: 24 時間)プロパティを抑制し運用にアラートすべき(SHOULD)。Key rotation
エージェントは、その well-known エージェント URL のagent-signing-key.json 経由で新しい署名鍵を公開します。ルーターは 5 分の TTL で鍵をキャッシュすべき(SHOULD)。署名が検証に失敗するとき、ルーターは拒否する前に鍵を再フェッチすべき(SHOULD) — エージェントがローテートしたかもしれない。
Key revocation
ローテーションは鍵を置き換え、失効は 1 つを殺します。失効は、秘密鍵が漏洩したと知られているか疑われる侵害のケースのためです。 パブリッシャーは、agent-signing-key.json の鍵エントリに revoked_at(ISO 8601 タイムスタンプ)を設定し、古いキャッシュが依然としてそれを見つけられるよう猶予期間中に鍵を trust anchor に残すことで、侵害された鍵をマークします。検証者は次をしなければなりません(MUST):
revoked_atが存在し署名エポックが失効タイムスタンプ以降に落ちる鍵で生成された任意の署名を拒否する。- 最後のキャッシュリフレッシュの後に伝播した失効を拾うため、拒否する前に検証失敗で
agent-signing-key.jsonを再フェッチする。 - 問題のあるリクエストについて失効を再試行不可として扱う — 「リトライで動くかも」の状態はない。
revoked_at マーカーを維持する。
失効の制限。 失効は 5 分以内(キャッシュ TTL)に伝播するが、失効が観測される前にプロバイダーによって既に受け入れられた署名を遡及的に無効化しない。revoked_at より前の署名エポックを持つキャプチャされた署名は、48 時間のリプレイウィンドウの残りの間検証可能なまま。侵害を疑うオペレーターは次をすべき(SHOULD):
- 確認された漏洩だけでなく、任意の疑いで先制的にローテートする。
- そもそも侵害の可能性を最小化するため、署名鍵をディスクではなく HSM または KMS に保つ。
- 日次エポックのロールオーバーがそれを含む署名されたペイロードを退役させるまで、漏洩した鍵が最大約 48 時間の偽造能力を付与することを受け入れる。このウィンドウが受け入れられないとき、より短いカスタムエポックウィンドウがデプロイオプション。
Key distribution
パブリッシャーの公開鍵はプロパティレジストリ経由で配布されます。各プロパティレコードはパブリッシャーの Ed25519 公開鍵を含みます。プロバイダーは起動時にレジストリをダウンロードし、増分同期経由で最新に保ちます。Wire Format
コンテンツタイプ:application/json
すべての TMP メッセージは JSON エンコーディングを使います。フィールド名とタイプはこの仕様の JSON Schema 定義に従います。実装は JSON をサポートしなければなりません(MUST)。
TMP メッセージは小さい(リクエスト/レスポンスごとに 200-600 バイト)。これらのサイズでは、シリアライゼーション形式は総レイテンシーの 1% 未満 — プロトコルのパフォーマンスは、エンコーディング効率ではなく、より小さいメッセージと構造的分離から来る。JSON はユニバーサルで、デバッグ可能で、すべての言語とツールでサポートされる。
Country-Partitioned Identity
アイデンティティデータは国(ISO 3166-1 alpha-2)で論理的に分割されます。プロトコルはすべての Identity Match リクエストとすべての TMPX トークンに国コードを運びます(バイヤーの読み取りレプリカは、データレジデンシールーティングのため暗号化された平文に国を含める — これはバイヤー内部でパブリッシャーやルーターに可視でない)。国が物理的にどうデータベースクラスターにグループ化されるかはデプロイ決定 — プロトコルはそれを制約しない。 パブリッシャーはルーティングディレクティブとして Identity Match リクエストにcountry フィールドを含めます。ルーターはそれを使って countries リストがその国コードを含むプロバイダーを選択し、次に転送前にフィールドを剥がします。バイヤーエージェントは決して国を見ません — アイデンティティシグナルではありません。
各プロバイダーエントリは、countries と uid_types フィールド経由でどの国とアイデンティティタイプを提供するかを宣言します。マルチカントリーのバイヤーはクラスターごとに別々のプロバイダーエントリを運用します(例: 米国に 1 つ、EU 諸国に 1 つ)。これにより、バイヤーはデータレジデンシー要件に準拠し、提供する国のみにパブリッシャーをサブスクライブし、プロトコル変更なしにクラスター間で国を移動できます。
TMPX Exposure Tokens
TMP は暗号化された露出トークン(TMPX)を使ってフリークエンシーキャッピングのループを閉じます。Identity Match 読み取りレプリカは、解決されたアイデンティティトークンを、クリエイティブトラッキング URL を通じて流れる不透明な TMPX マクロに暗号化します。バイヤーのインプレッションピクセルがトークンを復号しユーザーごとの露出をログします。Encryption
TMPX はmode_base で HPKE(RFC 9180)を使います:
バイヤーのクラスターマスターが受信者秘密鍵を保持します。読み取りレプリカはマスターの公開鍵を使って暗号化します。マスターのみが復号できます。TMPX トークンの偽造は、マスターの公開鍵(公開)とアイデンティティプロバイダー(UID2、ID5、RampID)からの現実的なアイデンティティトークンの両方を要求します — これらを捏造することは詐欺自体より難しい。系統的なフリークエンシー操作は、暗号化層ではなく IVT(Invalid Traffic)層で検出されます。
Binary format
TMPX 平文はコンパクトなバイナリ構造です。タイプ ID がトークン長を暗黙的に定義します — 長さプレフィックスは不要です。 ヘッダー(16 バイト):
エントリ(繰り返し、バイヤー設定の優先順位順):
Type ID レジストリ:
Type ID は安定 — 新しいタイプは追加され、既存の ID は決して変わらない。トークンはバイナリで保存される(UUID は 16 バイト、base64 エンコードされたトークンはデコード)。RampID は、維持された(XY、32 バイト)形式と派生された(Xi、48 バイト)形式がサイズで異なるため 2 エントリを持つ。
world_id_nullifier は relying-party スコープ: そのトークンは、証明の relying_party_id の 16 バイト SHA-256 ダイジェストに続く 32 バイトの nullifier。このエントリは 検証済み アテステーションからのみ生成される — 受信者確認された rp_id の下の検証者由来の nullifier(Verified Identity Attestation を参照)。identities[] の送信者アサートの world_id_nullifier は信頼を運ばず決して解決も封印もされない。検証済み rp_id を欠くため、このトークンさえ形成できない。uid2/id5/rampid とは異なり、エントリはバイヤーが解決するグラフ識別子ではない — 人格証明の仮名で、付随する検証済みアテステーションとともにのみ有効。World ID nullifier はそれが鋳造された rp_id 内でのみ意味を持ち、その rp_id はリクエスト側の attestation に乗り、トークンにラウンドトリップしない。トークンに rp_id ダイジェストを運ぶことで、帯域外のインプレッショントラッカーが nullifier をその relying party に帰属させ(受け入れる relying parties に対してダイジェストをマッチング)、(rp_id, nullifier) ペアでフリークエンシー状態をキー付けできる。そのため、ある relying party の下の nullifier は別のものとキャップ状態を決して共有しない。トークンは rp_id 平文を運ばず、ダイジェスト幅はワーキンググループのオープン項目。
パーサーが未知の Type ID に遭遇した場合、パースを停止し残りのエントリを absent として扱わなければならない(MUST)。ヘッダー Count フィールドは総エントリを示すが、実装はすべてのエントリがパース可能と仮定してはならない(MUST NOT) — 前方互換性は、より新しい Type ID が存在するときの優雅な劣化を要求する。
Wire format
TMPX マクロ値は<kid>.<base64url_ciphertext> 形式を使います。ciphertext はパディングなし base64url エンコーディング(RFC 4648 セクション 5、= パディング文字なし)を使わなければなりません(MUST)。パディング文字は = がキー値デリミタである URL クエリパラメーターを壊します。kid(鍵識別子、最大 8 文字)は不透明 — 地理的またはデプロイ情報をエンコードしてはなりません(MUST NOT)。内部的にクラスターマスター秘密鍵にマップします。
サイズ予算(255 文字 GAM マクロ制限): HPKE オーバーヘッド(48 バイト)とヘッダー(16 バイト)の後、アイデンティティエントリに約 120 バイト残る。3 つの 32 バイトトークン = 99 バイト — 快適に収まる。バイヤーが予算に収まるより多くのアイデンティティを解決するとき、TMPX 平文はバイヤーデプロイ設定に従って最高優先のエントリに切り詰められる。優先順位はバイヤー側の設定の関心事(プロトコルレベルでない)で、通常決定論的グラフ(UID2、RampID)を確率的またはパブリッシャースコープの識別子より上にランク付けする。バイヤーは明示的な優先リストを設定しなければならず(MUST) — デフォルト実装は恣意的に切り詰めてはならない(MUST NOT) — リストはバイヤーの運用ランブックに文書化すべき(SHOULD)。
Key management
クラスターごとに 1 つの X25519 キーペア:- クラスターマスターが復号のための 秘密鍵 を保持する。
- 公開鍵 は
adagents.jsonのエージェント認可エントリのencryption_keysに公開される。 - 読み取りレプリカは公開鍵を使って暗号化する。レプリカごとの鍵管理なし。
Replay protection
8 バイトのランダム nonce がマスターでの重複排除を可能にする。マスターは設定可能なウィンドウ(推奨: 7 日)nonce を保存し重複を拒否する。nonce は AEAD 保護された ciphertext の内側にある — 仲介者はそれを観測できない。Caching behavior
TMPX トークンは Identity Match 評価ごとに一度生成され、serve_window_sec ウィンドウの間適格性レスポンスに付随する。そのウィンドウ内の適格なパッケージのすべてのインプレッションは同じ TMPX 値(同じ nonce、同じトークン)を共有する。
バイヤーのマスターは、サーブウィンドウ内で TMPX 値や nonce で重複排除してはならない(MUST NOT) — 各ピクセル発火は 1 インプレッション。CTV ポッドまたは複数の広告ユニットを持つ web ページで同じユーザーに提供される複数の広告はすべて、同じ TMPX トークンで distinct なピクセル発火を生成する。nonce 重複排除は、サーブウィンドウが期限切れになった 後 の同じ TMPX トークンのリプレイのみを防ぐ — 同じ nonce が元のウィンドウ外に現れたら、それはリプレイで拒否されなければならない(MUST)。
Publisher obligations
パブリッシャーは TMPX 値をパース、復号、またはそれに基づいて決定してはならない(MUST NOT)。トークンは、他のマクロと正確に同様にクリエイティブトラッキング URL に代入される不透明なパススルーデータ。DOOH インベントリについては、プレーヤーは露出再照合のためバイヤーに送信される play log レコードに不透明な TMPX 値を含めてもよい(MAY) — パブリッシャーは送信ウィンドウを超えて TMPX 値を保持してはならない(MUST NOT)。Inventory-specific behavior
各ターミナルサーフェスについて、パブリッシャーは各アイデンティティプロバイダーがそのtmpx_macros 登録エントリで宣言したマクロ名(例: PIN_TMPX_1、NOVA_TMPX_1)をトラフィックする — それらの名前はアドサーバーラインアイテムがターゲットにする運用コントラクト。提供時に、パブリッシャーはレスポンスから tmpx_providers[provider_id].macros[] をたどり、各エントリの value を name で名付けられたスロットに逐語的に代入する。レガシー {TMPX} マクロ(非推奨の単数 tmpx フィールドから)は、移行していないコンシューマーのためサポートされたまま。
- Web、モバイル、CTV(SSAI)、音声(DAI): 標準インプレッションピクセル — 各
tmpx_providers[*].macros[].valueを一致するアドサーバーマクロスロットに代入する。 - CTV(クライアント側 VAST): パブリッシャーは VAST ドキュメントがプレーヤーに到達する前に同じマクロごとの代入を実行する。
- DOOH: Play-log ベース — TMPX 値はピクセル URL ではなく DOOH プレーヤーによってログされ play log レコードに含まれる。プロバイダーごとのマクロ/値ペアは、バイヤーが正しい復号マスターにルーティングできるよう、その
provider_idとともにログされなければならない(MUST)。
Transport
- HTTP/2 POST 上の JSON。すべての実装はこのトランスポートを使わなければならない(MUST)。
- 各プロバイダーはそのベース URL の下に 2 つのパスベースのエンドポイントを公開する: Context Match の
POST /contextと Identity Match のPOST /identity。ルーターは、メッセージボディを検査するのではなく、パスでリクエストをディスパッチする。 - 各プロバイダーはそのベース URL で
GET /healthを公開すべき(SHOULD)。エンドポイントは、プロバイダーがリクエストを受け入れる準備ができたとき HTTP200を JSON ボディ{"status": "ok"}とともに返す。任意の非200レスポンスまたは接続失敗はプロバイダーが準備未完了を意味する。ルーターとオペレーターはこれをプリフライトチェックと監視に使う — リクエストのホットパスでは呼ばれない。 - 各メッセージの
typeフィールドはデシリアライゼーションのためにメッセージを識別する — ルーターとエージェントはそれを、ルーティングではなく正しいスキーマを選択するのに使う。エージェントはtypeフィールドがエンドポイントに一致することを検証しなければならない(MUST):/contextのcontext_match_request、/identityのidentity_match_request。不一致は HTTP400で拒否されなければならない(MUST)。 - 接続は HTTP/2 多重化経由で再利用すべき(SHOULD)。
- ルーターは各バイヤーエージェントへの接続プールを維持すべき(SHOULD)。
- adcp-go SDK がリファレンスクライアントとサーバー実装を提供する。適合性テストが互換性を検証する — 他の言語の実装は同じテストスイートに合格しなければならない(MUST)。
HTTP Status Codes
TMP はトランスポートレベルのエラーにのみ HTTP ステータスコードを使います。アプリケーションレベルの結果(TMP エラーレスポンスを含む)は常に HTTP200 で返されます:
これは、空の
offers 配列を持つ 200 が有効な「一致なし」レスポンスで、TMP エラーボディ("type": "error")を持つ 200 が有効なアプリケーションエラーであることを意味します。ルーターは結果にかかわらず 1 つのレスポンス形式を扱います。
Latency
- TMP は 50ms 未満のエンドツーエンドレイテンシー(publisher → router → agents → router → publisher)をターゲットにする。
- ルーターは、観測されたレイテンシーパーセンタイルに基づいてエージェントごとの適応的タイムアウトを適用すべき(SHOULD)。
- タイムアウトを超えるエージェントは、そのリクエストのマージされたレスポンスから除外される。
- ルーターは、p95 レイテンシーが一貫して予算を超えるエージェントを先制的にスキップしてもよい(MAY)。
Caching
Context Match レスポンスは、同じパッケージが特定のプレースメントのすべてのユーザーについて評価されるためキャッシュ可能です。推奨キャッシュキーは{property_rid, placement_id, provider_id}。
- ルーターは Context Match レスポンスを 5 分 の TTL でキャッシュすべき(SHOULD)。
- プロバイダーは Context Match レスポンスに
cache_ttlフィールド(integer、秒)を含めてデフォルトを上書きしてもよい(MAY)。ルーターは存在するときこの値を尊重しなければならない(MUST)。 - Identity Match レスポンスは
serve_window_sec(パッケージごとのシングルショット fcap、最大 300s、デフォルト 60s)で束縛される。ルーターは{identities_hash, provider_id, package_ids_hash, consent_hash, sealed_credentials_hash}でキー付けされた内部重複排除キャッシュを適用してもよい(MAY)。ここでidentities_hashは Identity Match signed fields で定義された正準identitiesバイトの SHA-256(プロバイダーごとにフィルターされたサブセットに対して計算)。package_ids_hashはソートされたpackage_ids配列の JCS シリアライゼーションに対する SHA-256。consent_hashはリクエストのconsentオブジェクトの JCS シリアライゼーション(フィールドが欠如のとき JCSnull— これは「同意不明」を明示的に空の consent オブジェクトと区別する)に対する SHA-256。sealed_credentials_hash(実験的、trusted_match.verified_identity)は Identity Match signed fields で定義された正準sealed_credentialsバイトの SHA-256、または欠如のときnull— そのため適格性をシフトさせるネットワーク認証情報の変更が、古いレスポンスを提供するのではなくキャッシュを再分割する。JCS フレーミングがデリミタ注入を防ぐ:|、,、\nを含む生の consent 文字列やパッケージ ID が 2 つの distinct な入力を衝突させられない。アイデンティティセットを含めることは、トークンの追加や削除が distinct なキャッシュエントリを生成することを保証する。パッケージリストハッシュを含めることは、アクティブなパッケージセットが変わるとき(例: 新しいメディアバイがアクティベート)キャッシュされたレスポンスが無効化されることを保証する。consent ハッシュを含めることは、ある consent 状態の下で取られた適格性決定が別の下で提供されるのを防ぐ。パブリッシャーの拘束コントラクトは、ルーターの内部キャッシュウィンドウではなくサーブウィンドウスロットル。 - プロバイダーのターゲティング設定が変わるとき(新しいパッケージ、更新されたターゲティングルール)、プロバイダーは変更が伝播するまで
"cache_ttl": 0(Context Match)または"serve_window_sec": 1(Identity Match)を返し、その後通常値を再開すべき(SHOULD)。 cache_ttl(Context Match)はスキーマ強制の最大 86400 秒を持つ。serve_window_secは 300 秒に束縛される — より長いウィンドウはパッケージごとの fcap を典型的なキャンペーンに粗すぎにし、IdentityMatch 往復より短いものはスロットルを無駄にする。
Conformance Levels
TMP Buyer Agent (Basic)
context_matchケイパビリティをサポート- ContextMatchRequest に有効な ContextMatchResponse で応答
- レイテンシー予算を満たす(エージェント側処理で p95 < 30ms)
- プライバシー制約を尊重する(他のソースからのアイデンティティデータでリクエストをログまたは相関しない)
TMP Buyer Agent (Full)
Basic のすべて、加えて:identity_matchケイパビリティをサポート- IdentityMatchRequest に有効な IdentityMatchResponse(適格なパッケージ ID + TTL)で応答
- プロダクトが一致する
response_typesを宣言するときリッチなオファー(ブランド、価格、summary、クリエイティブマニフェスト)をサポート
TMP Router (Basic)
- プロバイダーエンドポイントで設定
- Context Match と Identity Match を認可されたプロバイダーにファンアウト
- レスポンスをマージ
- エンドツーエンドレイテンシー予算を満たす(p95 < 50ms)
TMP Router (Trusted)
Basic のすべて、加えて:- TEE アテスト済み環境(例: AWS Nitro Enclaves)で実行
- リクエストに応じてアテステーションドキュメントを提供し、デプロイされたバイナリが公開されたソースに一致することを証明
- コンテキストとアイデンティティのコードパス間の構造的分離がアテステーション測定経由で検証可能