> ## Documentation Index
> Fetch the complete documentation index at: https://adcp-docs-ja.pier1.co.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# マネージドネットワークデプロイ

> マネージドパブリッシャーネットワークが、URL 参照パターン、委譲タイプ、一般的なインフラアプローチを使って、数千のドメイン全体で adagents.json をどうデプロイするか。

マネージド広告ネットワーク（例: 数百または数千のパブリッシャードメインを運用するネットワーク）は、既に HTTP リダイレクトまたは集中ホスティング経由で `ads.txt` を配布しています。`adagents.json` は組み込みの委譲モデルを通じて同じスケールをサポートします: [URL 参照パターン](/docs/governance/property/adagents#url-reference-pattern)。

このガイドは、既存の `ads.txt` デプロイ知識を `adagents.json` にマップし、ネットワークスケールで機能するインフラパターンをカバーします。

## ads.txt 配布との比較

`ads.txt` と `adagents.json` の両方が、各パブリッシャーオリジンの well-known パスにファイルを要求します。デプロイの仕組みは似ていますが、`adagents.json` には、ネットワークが `ads.txt` に通常使う HTTP リダイレクトパターンを置き換える組み込みの委譲モデルがあります。

| Concern      | `ads.txt`                   | `adagents.json`                         |
| ------------ | --------------------------- | --------------------------------------- |
| ファイル位置       | `/ads.txt`                  | `/.well-known/adagents.json`            |
| 委譲メカニズム      | HTTP 301/302 リダイレクト         | `authoritative_location` フィールド（ファイル内参照） |
| 委譲が表現するもの    | 「このファイルは別の場所に存在する」          | 「このパブリッシャーは名指しされた権威に委譲する」               |
| パブリッシャーの意図   | 曖昧（リダイレクトはインフラかも）           | 明示的（ポインターファイルは宣言）                       |
| 認可のスコープ      | フラット（`DIRECT` / `RESELLER`） | 構造化（プロパティ、プレースメント、国、時間ウィンドウ、委譲タイプ）      |
| スケールでのキャッシング | 各ドメインが独立にキャッシュ（重複排除なし）      | 検証者はそれを参照するすべてのドメインの 1 つの権威ファイルをキャッシュ   |
| ファイル形式       | プレーンテキスト、行ごと 1 エントリー        | スキーマ検証付き JSON                           |

キーの違い: HTTP リダイレクトは消費者に不可視です。301 をフォローする検証者は、リダイレクトが「パブリッシャーがこのネットワークに委譲する」を意味するか「CDN がパスを再編成した」を意味するかを判別できません。`authoritative_location` フィールドは委譲を明示的なパブリッシャー宣言にします。

## ポインターファイルパターン

各マネージドドメインは `/.well-known/adagents.json` に最小限のポインターファイルをホストします。ポインターは、ネットワークが保守する 1 つの集中化された権威ファイルを参照します。

**ポインターファイル**（各ドメイン上）:

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
  "authoritative_location": "https://network.example.com/adagents/v2/adagents.json",
  "last_updated": "2025-06-01T00:00:00Z"
}
```

ポインターファイルの `last_updated` タイムスタンプは、権威ファイルが更新されたときではなく、ポインター自体が最後に変更されたとき（例: `authoritative_location` URL が変わったとき）を反映します。権威ファイルは自身の `last_updated` を運びます。

**権威ファイル**（ネットワークにて）:

```json theme={null}
{
  "$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
  "contact": {
    "name": "Example Network Ad Operations",
    "email": "adops@network.example.com",
    "domain": "network.example.com"
  },
  "properties": [
    {
      "property_id": "site_cooking_daily",
      "property_type": "website",
      "name": "Cooking Daily",
      "identifiers": [{"type": "domain", "value": "cookingdaily.com"}],
      "tags": ["food", "managed_network"],
      "publisher_domain": "cookingdaily.com"
    },
    {
      "property_id": "site_garden_weekly",
      "property_type": "website",
      "name": "Garden Weekly",
      "identifiers": [{"type": "domain", "value": "gardenweekly.com"}],
      "tags": ["home", "managed_network"],
      "publisher_domain": "gardenweekly.com"
    }
  ],
  "tags": {
    "managed_network": {
      "name": "Managed Network",
      "description": "All domains managed by Example Network"
    }
  },
  "authorized_agents": [
    {
      "url": "https://sales.network.example.com",
      "authorized_for": "All managed network properties",
      "authorization_type": "property_tags",
      "property_tags": ["managed_network"],
      "delegation_type": "ad_network"
    }
  ],
  "last_updated": "2025-06-01T00:00:00Z"
}
```

### 検証者がポインターファイルをどう解決するか

```mermaid theme={null}
sequenceDiagram
    participant V as Validator
    participant P as cookingdaily.com
    participant N as network.example.com

    V->>P: GET /.well-known/adagents.json
    P-->>V: {"authoritative_location": "https://network.example.com/..."}
    Note over V: Detect pointer — single hop allowed
    V->>N: GET /adagents/v2/adagents.json
    N-->>V: Full adagents.json (properties, agents, placements)
    Note over V: Verify: no nested authoritative_location
    Note over V: Validate against schema
```

検証者はポインターファイルをフェッチし、`authoritative_location` URL をフォローし、権威ファイルを通常のインライン構造として検証します。

**単一ホップのみ。** 権威ファイルはそれ自体で `authoritative_location` を含んではなりません。これはリダイレクトチェーンと無限ループを防ぎます。

### 1 つの権威ファイル対パブリッシャーごとのファイル

上の例は、すべてのドメインが同じ権威ファイルを指すことを示します。これは、すべてのパブリッシャーが同じエージェント、委譲タイプ、プレースメント構造を共有するときに機能します。

パブリッシャーごとの権威ファイルは、取り決めがネットワーク全体で異なるときに意味をなします:

* 異なるパブリッシャーが異なるエージェントを認可（一部はネットワークと並んで自身の直接販売を持つ）
* 異なる委譲タイプ（パブリッシャー A は `ad_network` のみ、パブリッシャー B はプレミアムプレースメントの `direct` パスを保持）
* 異なるプレースメント構造（あるパブリッシャーは `pre_roll` と `host_read` を持ち、別のは `display_banner` のみ）
* `property_features` の異なるガバナンスベンダー

このモデルでは、各ポインターファイルはパブリッシャー固有の URL を参照します:

```
cookingdaily.com/.well-known/adagents.json
  → "authoritative_location": "https://network.example.com/adagents/cookingdaily.json"

gardenweekly.com/.well-known/adagents.json
  → "authoritative_location": "https://network.example.com/adagents/gardenweekly.json"
```

ネットワークは依然としてすべての権威ファイルを集中ホストします — ポインターファイルは異なるパスを参照するだけです。[CI/CD pipeline](#cicd-pipeline) パターンは自然なフィットです: 中央データベースからパブリッシャーごとの権威ファイルを生成しネットワークの CDN にデプロイします。

1 つの共有ファイルで始めてください。パブリッシャーが個別の取り決めを交渉するにつれパブリッシャーごとのファイルに移行します。

### Why not HTTP redirects?

HTTP リダイレクトは `ads.txt` に機能します。なぜなら `ads.txt` は自己参照セマンティクスのないフラットリストだからです。クローラーはリダイレクトチェーンをフォローし最終ファイルを検証します。

`adagents.json` には、HTTP リダイレクトは問題を引き起こします:

* **曖昧な意図。** リダイレクトは委譲、インフラ移行、または CDN ルーティングを意味しうる。ポインターファイルは委譲を明示的に宣言します。
* **スコーピングなし。** HTTP リダイレクトは全か無かです。ポインターファイルは、ネットワークが販売を認可された正確なものを宣言できる構造化された認可モデルと並びます。
* **キャッシングペナルティ。** HTTP リダイレクトでは、検証者は 10,000 のドメインすべてが同じファイルにリダイレクトすることを知る方法がありません。各レスポンスを独立として扱わなければなりません — 同一コンテンツの 10,000 キャッシュエントリー。`authoritative_location` では、検証者はすべてのポインターファイル全体で同じ URL を見て権威ファイルを一度キャッシュします。数千のドメインを持つネットワークには、これは 1 キャッシュエントリーと数千の違いです。

それらの問題は、リダイレクトを使って **委譲** を表現すること — 「私の認可は別の場所に存在する」と言うクロスドメインホップ — についてです。それが `authoritative_location` が置き換えるものです。それらは **ホスティング正規化** についてではありません。それはパブリッシャーのアペックスドメインが `www` に `301` リダイレクトする通常のケース（ほとんどのマネージドホスティングと CDN のデフォルト）です。2 つはリダイレクトがどこを指すかで区別されるため、フェッチルールはそれに応じて分割されます:

* **同一登録可能ドメインのリダイレクトはフォローされなければなりません（MUST）** — `/.well-known/adagents.json` フェッチで — `apex ↔ www`、および同じ登録可能ドメイン（eTLD+1）に留まる任意のリダイレクト — すべてのホップで [SSRF 制御](/docs/building/by-layer/L1/security#webhook-url-validation-ssrf) を再検証し、非 HTTPS スキームへの任意のリダイレクトを拒否し、チェーンを 3 ホップで上限とします。これらを黙って拒否することは、正しく構成されたパブリッシャーを未認可としてレポートします。同一登録可能ドメイン比較は、前のホップではなくすべてのホップで **元々リクエストされた** ドメインにアンカーされなければならず（MUST）、`same → cross` の 2 ホップチェーンがそれを逃れられないようにします。
* **クロス登録可能ドメインのリダイレクトはこのフェッチで拒否されなければなりません（MUST）。** クロスドメインリダイレクトは、このパターンが置き換えるために存在する曖昧でスコープされていない委譲シグナルです — 代わりに `authoritative_location` で委譲を明示的に宣言します。検証者はリダイレクト **拒否** で `authoritative_location` を 2 番目のホップとしてデリファレンスします（[Security considerations](#security-considerations) を参照）: 名指しされた URL が宣言された権威的位置であり、そこから離れるリダイレクトはその宣言を変えます。

## 正しい委譲タイプの選択

ネットワークがマネージドパブリッシャーに代わってエージェントを認可するとき、`delegation_type` フィールドは商業関係を記述します:

| `delegation_type` | Use when                                       | Example                               |
| ----------------- | ---------------------------------------------- | ------------------------------------- |
| `direct`          | ネットワークが運用してもパブリッシャーがこれを自身の販売チャネルとして扱う          | パブリッシャーとしてブランド化されたホワイトラベルセールスエージェント   |
| `delegated`       | パブリッシャーがネットワークに代わって販売することを認可                   | 明示的なパブリッシャー契約を持つレップファーム               |
| `ad_network`      | 在庫はパブリッシャーのエンドポイントとしてではなくネットワークのパッケージを通じて販売される | ポートフォリオ全体で販売する Mediavine 型マネージドネットワーク |

ほとんどのマネージドネットワークは `ad_network` を使います。個別のパブリッシャーが自身の商業アイデンティティを維持するがネットワークが彼らを代表することを認可するとき `delegated` を使います。ネットワークがパブリッシャーが自身の販売インフラとして提示するものを運用するときのみ `direct` を使います。

単一の権威ファイルは委譲タイプを混合できます — 異なるエージェントが同じ在庫と異なる関係を持てます:

```json theme={null}
{
  "authorized_agents": [
    {
      "url": "https://sales.network.example.com",
      "authorized_for": "Network-sold inventory across all managed properties",
      "authorization_type": "property_tags",
      "property_tags": ["managed_network"],
      "delegation_type": "ad_network"
    },
    {
      "url": "https://premium.publisher.example.com",
      "authorized_for": "Publisher's direct premium sales",
      "authorization_type": "property_ids",
      "property_ids": ["site_cooking_daily"],
      "delegation_type": "direct",
      "placement_tags": ["premium"],
      "exclusive": true
    }
  ]
}
```

## プロパティタグでファイルを効率的に保つ

500 のプロパティと 3 つの認可エージェントを持つマネージドネットワークは、すべてのエージェントエントリーですべてのプロパティ ID をリストできます — しかしそれは 1,500 のプロパティ対エージェントマッピングの保守を意味します。プロパティタグはその冗長性を排除します。

原則: **各プロパティを一度リスト** し、その識別子とタグを付け、次に **エージェントをタグで認可** します。

```json theme={null}
{
  "properties": [
    {
      "property_id": "site_cooking_daily",
      "property_type": "website",
      "name": "Cooking Daily",
      "identifiers": [{"type": "domain", "value": "cookingdaily.com"}],
      "tags": ["managed_network", "food"],
      "publisher_domain": "cookingdaily.com"
    },
    {
      "property_id": "site_garden_weekly",
      "property_type": "website",
      "name": "Garden Weekly",
      "identifiers": [{"type": "domain", "value": "gardenweekly.com"}],
      "tags": ["managed_network", "home"],
      "publisher_domain": "gardenweekly.com"
    }
  ],
  "tags": {
    "managed_network": {
      "name": "Managed Network",
      "description": "All domains managed by Example Network"
    },
    "food": {
      "name": "Food & Cooking",
      "description": "Food and cooking content verticals"
    },
    "home": {
      "name": "Home & Garden",
      "description": "Home and garden content verticals"
    }
  },
  "authorized_agents": [
    {
      "url": "https://sales.network.example.com",
      "authorized_for": "All managed network properties",
      "authorization_type": "property_tags",
      "property_tags": ["managed_network"],
      "delegation_type": "ad_network"
    },
    {
      "url": "https://food-vertical-agent.example.com",
      "authorized_for": "Food vertical properties only",
      "authorization_type": "property_tags",
      "property_tags": ["food"],
      "delegation_type": "delegated"
    }
  ]
}
```

各プロパティは一度現れます。タグがマッピングを処理します。新しいドメインがネットワークに参加するとき、正しいタグで `properties` に追加します — 認可エントリーは変更不要です。新しいバーティカルエージェントが加わるとき、関連タグで 1 つのエージェントエントリーを追加します。

これはファイルを、数千のプロパティでも可読、保守可能、コンパクトに保ちます。

## 単一の認可の下で多くのパブリッシャーを表現する

上のパターンは、自身のプロパティをリストする単一のパブリッシャーの `adagents.json` 用です。多くの *他の* パブリッシャーを表現するマネージドネットワーク（WordPress ネットワーク、コンテンツレコメンデーションネットワーク、マルチプロパティホールディングカンパニー構成）は、各表現されるパブリッシャーに代わってどのエージェントが販売を認可されるかを宣言する 1 つの権威ファイルをホストします。

すべての表現されるパブリッシャーが同じタグ述語の下で同じエージェントに委譲するとき — 正準マネージドネットワーク形状 — `publisher_properties` のコンパクトな `publisher_domains[]` 形式を使います:

```json theme={null}
{
  "authorized_agents": [{
    "url": "https://agent.network.example/api",
    "authorized_for": "Managed-network inventory across represented publishers",
    "authorization_type": "publisher_properties",
    "publisher_properties": [{
      "publisher_domains": ["site1.example", "site2.example", "site3.example"],
      "selection_type": "by_tag",
      "property_tags": ["managed_network"]
    }],
    "delegation_type": "ad_network"
  }]
}
```

パブリッシャーごとではなく共有セレクター述語ごとに 1 エントリー。上記は、リストされた各ドメインごとに単数形式エントリーを繰り返すのとセマンティックに同一です。完全な仕組み、単数対コンパクトコントラクト、`managerdomain` ads.txt フォールバックとの相互作用については [adagents.json リファレンスの Pattern 4](/docs/governance/property/adagents#pattern-4-publisher-property-references) を参照してください。コンパクト形式は、表現されるパブリッシャー数ではなく *異なるセレクター述語の数*（通常は小さな定数）と線形にスケールします。

## プレースメントで各エージェントが何を販売できるかを制御する

すべての認可されたセラーがすべてにアクセスできるように見える `ads.txt` と異なり、`adagents.json` はネットワークが各エージェントが販売を認可された正確なプレースメントを宣言できるようにします。これは販売レバレッジを保持します — バイヤーはプレミアム在庫が特定のパスを通じてのみ利用可能であることを見られます。

トップレベルで一度プレースメントを定義し、グループ化のためタグ付けし、次に各エージェントの認可を特定のプレースメントタグにスコープします:

```json theme={null}
{
  "placement_tags": {
    "programmatic": {
      "name": "Programmatic",
      "description": "Placements available through programmatic sales paths"
    },
    "direct_only": {
      "name": "Direct only",
      "description": "Premium placements reserved for direct network sales"
    }
  },
  "placements": [
    {
      "placement_id": "bottom_native_feed",
      "name": "Bottom-of-page native feed",
      "tags": ["programmatic"],
      "property_tags": ["managed_network"]
    },
    {
      "placement_id": "page_takeover",
      "name": "Full-page takeover",
      "tags": ["direct_only", "premium"],
      "property_tags": ["managed_network"]
    },
    {
      "placement_id": "sidebar_display",
      "name": "Sidebar display",
      "tags": ["programmatic"],
      "property_tags": ["managed_network"]
    }
  ],
  "authorized_agents": [
    {
      "url": "https://taboola.com/agent",
      "authorized_for": "Bottom-of-page native feed across all managed properties",
      "authorization_type": "property_tags",
      "property_tags": ["managed_network"],
      "placement_tags": ["programmatic"],
      "delegation_type": "ad_network"
    },
    {
      "url": "https://sales.network.example.com",
      "authorized_for": "Premium direct-sold placements",
      "authorization_type": "property_tags",
      "property_tags": ["managed_network"],
      "placement_tags": ["direct_only"],
      "delegation_type": "direct",
      "exclusive": true
    }
  ]
}
```

この例では、Taboola はプログラマティックプレースメント（ページ下部ネイティブフィードとサイドバー）のみを販売できます。ネットワーク自身の販売チームがページテイクオーバーへの排他的アクセスを持ちます。このファイルを読むバイヤーエージェントは、どのパスがどの在庫につながるかを正確に知ります — 誰が何を販売できるかについて曖昧性はありません。

## 追加の認可修飾子

プロパティタグとプレースメントタグを超えて、エージェントは以下でスコープできます:

* **`countries`** — 地理で制限（例: `["US", "CA"]`）
* **`effective_from` / `effective_until`** — 季節または試用取り決めのための時間制限付き認可
* **`exclusive`** — これがスコープされた在庫の唯一の認可パスかを宣言

## パブリッシャーが認可しているもの

パブリッシャーのドメインがポインターファイルをホストするとき、彼らは権威ファイルが彼らを代弁すると宣言しています。これは意味します:

* 権威ファイルにリストされたエージェントはパブリッシャーの在庫を販売する認可を受けている
* 各エージェントエントリーの `delegation_type` は商業関係を記述する
* 修飾子（`placement_tags`、`countries`、`exclusive` など）は各エージェントが何を販売できるかをスコープする

ネットワークがドメインインフラを運用する場合、パブリッシャーは通常ネットワーク契約を通じて既にこれに同意しています。しかしポインターファイルはその同意の機械可読な宣言です。パブリッシャーがネットワークを去る場合、ポインターファイルを削除または置き換えることが認可を即座に取り消します。

## Deployment patterns

これらのパターンはすべて同じことを達成します: 各マネージドドメインの `/.well-known/adagents.json` で静的 JSON ポインターファイルを提供します。既存のインフラに基づいて選んでください。

### CDN エッジ関数

CDN ワーカーまたはエッジ関数からポインターファイルを提供します。これは、パブリッシャーの DNS と CDN を既に管理するネットワークに最も一般的なパターンです。

**Cloudflare Worker:**

```javascript theme={null}
export default {
  async fetch(request) {
    const url = new URL(request.url);
    if (url.pathname === '/.well-known/adagents.json') {
      return new Response(JSON.stringify({
        "$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
        "authoritative_location": "https://network.example.com/adagents/v2/adagents.json",
        "last_updated": "2025-06-01T00:00:00Z"
      }), {
        headers: {
          'Content-Type': 'application/json',
          'Cache-Control': 'public, max-age=86400',
          'Access-Control-Allow-Origin': '*'
        }
      });
    }
    return fetch(request);
  }
};
```

**AWS CloudFront function:**

```javascript theme={null}
function handler(event) {
  if (event.request.uri === '/.well-known/adagents.json') {
    return {
      statusCode: 200,
      statusDescription: 'OK',
      headers: {
        'content-type': { value: 'application/json' },
        'cache-control': { value: 'public, max-age=86400' },
        'access-control-allow-origin': { value: '*' }
      },
      body: JSON.stringify({
        "$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
        "authoritative_location": "https://network.example.com/adagents/v2/adagents.json",
        "last_updated": "2025-06-01T00:00:00Z"
      })
    };
  }
  return event.request;
}
```

### CMS プラグイン

WordPress または類似の CMS インストールを管理するネットワークには、プラグインがサーバー構成に触れずにポインターファイルを提供できます。

**WordPress (mu-plugin):**

```php theme={null}
<?php
add_action('init', function () {
    if (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) === '/.well-known/adagents.json') {
        header('Content-Type: application/json');
        header('Cache-Control: public, max-age=86400');
        echo json_encode([
            '$schema' => 'https://adcontextprotocol.org/schemas/v3/adagents.json',
            'authoritative_location' => 'https://network.example.com/adagents/v2/adagents.json',
            'last_updated' => '2025-06-01T00:00:00Z',
        ]);
        exit;
    }
});
```

これをマネージドインストール全体で `wp-content/mu-plugins/` に置きます。Must-use プラグインはアクティベーションなしに自動的にロードされます。

### CI/CD pipeline

中央構成からポインターファイルを生成し、各サイトと並んで静的アセットとしてデプロイします。

**GitHub Actions example:**

```yaml theme={null}
name: Deploy adagents.json pointer files

on:
  push:
    branches: [main]
    paths: ['config/managed-domains.json']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate pointer files
        run: |
          TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
          for domain in $(jq -r '.domains[]' config/managed-domains.json); do
            mkdir -p "dist/${domain}/.well-known"
            cat > "dist/${domain}/.well-known/adagents.json" <<EOF
          {
            "\$schema": "https://adcontextprotocol.org/schemas/v3/adagents.json",
            "authoritative_location": "https://network.example.com/adagents/v2/adagents.json",
            "last_updated": "${TIMESTAMP}"
          }
          EOF
          done

      - name: Deploy to hosting
        run: # your deployment step here
```

### DNS + エッジ関数

ネットワークが DNS を管理するがオリジンサーバーは管理しない場合、CNAME とパスベースルーティングを使って well-known パスのみをエッジ関数を通じてルーティングします。

これは以下のとき機能します:

* パブリッシャーが自身のオリジンサーバーを制御する
* ネットワークが DNS を管理する（マネージドネットワーク契約で一般的）
* パブリッシャーのサーバーを変更せずに `adagents.json` を提供する必要がある

DNS プロバイダーを構成して `/.well-known/adagents.json` リクエストをネットワーク運用のエッジ関数（上の CDN エッジパターンを使用）にルーティングし、他のすべてのトラフィックをパブリッシャーのオリジンに通します。

具体的な構成は DNS と CDN プロバイダーに依存します。原則は同じです: well-known パスをインターセプトし、ポインターファイルを提供し、他のすべてを通す。

## デプロイの検証

### 単一ドメイン

```bash theme={null}
# Fetch the pointer file
curl -s https://cookingdaily.com/.well-known/adagents.json | jq .

# Follow the reference and validate the authoritative file
curl -s $(curl -s https://cookingdaily.com/.well-known/adagents.json | jq -r '.authoritative_location') | jq .
```

### AdCP クライアントの使用

`@adcp/sdk` パッケージは、すべてのマネージドドメイン全体でデプロイを検証し一般的な失敗モードを検出するネットワーク一貫性チェッカーを含みます:

```bash theme={null}
# Check all domains referencing an authoritative file
npx adcp check-network --url https://network.example.com/adagents/v2/adagents.json

# Check specific domains
npx adcp check-network --domains cookingdaily.com,gardenweekly.com

# JSON output for CI/CD pipelines
npx adcp check-network --url https://network.example.com/adagents/v2/adagents.json --json
```

プログラマティック使用:

```typescript theme={null}
import { NetworkConsistencyChecker } from '@adcp/sdk';

const checker = new NetworkConsistencyChecker({
  authoritativeUrl: 'https://network.example.com/adagents/v2/adagents.json',
});

const report = await checker.check();

console.log(`Coverage: ${report.coverage}%`);
console.log(`Orphaned pointers: ${report.orphanedPointers.length}`);
console.log(`Missing pointers: ${report.missingPointers.length}`);
console.log(`Schema errors: ${report.schemaErrors.length}`);
```

**[AdAgents.json Builder](https://agenticadvertising.org/adagents/builder)** を使って個別ドメインをインタラクティブに検証したり、プログラマティックチェックには [検証 API](/docs/governance/property/adagents#programmatic-validation) を使えます。

### CI/CD との統合

ポインターファイルをデプロイした後に一貫性チェッカーを実行し、バイヤーに影響する前に問題を捕捉します:

```yaml theme={null}
- name: Validate network deployment
  run: npx adcp check-network --url ${{ vars.AUTHORITATIVE_URL }} --json > report.json

- name: Check for failures
  run: |
    ISSUES=$(jq '.orphanedPointers + .stalePointers + .missingPointers + .schemaErrors | length' report.json)
    if [ "$ISSUES" -gt 0 ]; then
      echo "::error::Network consistency check found $ISSUES issues"
      jq '.' report.json
      exit 1
    fi
```

## トラブルシューティング

マネージドネットワークデプロイで発生する 5 つの失敗モード、それらの検出方法、修正方法。

### Orphaned pointer

**何が起こったか:** パブリッシャードメインがあなたの権威 URL を参照するポインターファイルを持つが、権威ファイルがそのドメインを `properties` にリストしていない。

**どう見えるか:** バイヤーエージェントが `cookingdaily.com/.well-known/adagents.json` をフェッチし、ネットワークの権威ファイルへのポインターをフォローし、`publisher_domain: "cookingdaily.com"` を持つプロパティを見つけない。ドメインはそれを主張しないネットワークに委譲するように見える。

**一般的な原因:** ネットワークがパブリッシャーを権威ファイルから削除した（例: 契約終了）が、ドメインのポインターファイルが削除されなかった。

**修正:** プロパティを権威ファイルに再追加するか、パブリッシャーのドメインのポインターファイルを削除/置き換えます。ネットワークがもはやドメインの DNS または CDN を管理しない場合、パブリッシャーと調整してポインターを削除します。

**検出:** `npx adcp check-network --url <authoritative_url>` がこれらを orphaned pointer としてレポートします。

### 古いポインター

**何が起こったか:** パブリッシャーのポインターファイルが、関係が終わった後もネットワークの権威 URL を依然として参照する。orphaned pointer に似ているが、パブリッシャーの視点から — ドメインがもはや認可しないネットワークへの委譲を依然として主張する。

**一般的な原因:** ネットワークがパブリッシャーを終了したがドメインのインフラを制御しない。パブリッシャーが well-known パスを更新していない。

**修正:** パブリッシャーがポインターファイルを更新または削除しなければならない。ネットワークは権威ファイルから彼らを削除するときパブリッシャーに通知すべき。AAO レジストリはクロール中にこの不一致を検出しネットワークヘルス監視で表示します。

### 欠けているポインター

**何が起こったか:** ドメインが権威ファイルの `properties` に（`publisher_domain` 経由で）リストされているが、そのドメインの `/.well-known/adagents.json` が存在しないか期待される権威 URL を指さない。

**どう見えるか:** ネットワークはドメインを表現すると主張するが、ドメインは委譲を確認しない。バイヤーエージェントは認可チェーンを検証できない。

**一般的な原因:** パブリッシャーが最近ネットワークに参加したがポインターファイルがまだデプロイされていない、またはデプロイが失敗した。

**修正:** 上の [deployment patterns](#deployment-patterns) の 1 つを使ってポインターファイルをドメインにデプロイします。以下で検証:

```bash theme={null}
curl -s https://newpublisher.com/.well-known/adagents.json | jq '.authoritative_location'
```

### スキーマエラー

**何が起こったか:** 権威ファイルに検証エラーがある — 不正な形式の JSON、欠けている必須フィールド、無効なフィールド値。

**影響:** 1 つの悪いデプロイが、すべてが同じファイルを参照するため、ネットワークのすべてのドメインの検証を壊します。

**修正:** デプロイ前に権威ファイルを検証:

```bash theme={null}
# Validate against the JSON schema
npx adcp check-network --url https://network.example.com/adagents/v2/adagents.json
```

開発中のインタラクティブ検証には [AdAgents.json Builder](https://agenticadvertising.org/adagents/builder) を使います。CI/CD パイプラインにプリデプロイチェックとしてスキーマ検証を追加します。

### エージェントエンドポイント到達不能

**何が起こったか:** `authorized_agents` エントリーの URL が応答しないかエラーを返す。バイヤーエージェントは認可で宣言されたセールスエージェントに到達できない。

**一般的な原因:** エージェントサービスがダウン、URL 変更、または DNS が誤構成。

**修正:** エージェントエンドポイントが到達可能で有効なエージェントカードを返すことを検証:

```bash theme={null}
# A2A agent
curl -s https://sales.network.example.com/.well-known/agent-card.json | jq .

# Check via AdCP client
npx adcp check-network --url <authoritative_url>
```

`check-network` コマンドはすべてのエージェントエンドポイントを検証し応答時間をレポートするため、バイヤーより前に遅いまたは失敗するエージェントを捕捉できます。

## Security considerations

権威ファイルへの 1 つのデプロイが、ネットワークのすべてのパブリッシャー全体で認可を変えます。そのスケールがポイントで、それはまた爆発半径です — 侵害されたネットワーク CDN は、数千のドメイン全体で悪意あるセールスエージェントを同時に認可できます。スキーマの正しさを超える 2 つの具体的な含意:

**検証者フェッチセマンティクス。** 権威 URL はネットワーク制御のオリジンを指します。明示的なフェッチルールなしでは、誤動作するオリジンがキャッシュを汚染したり検証者をハングさせたりできます。検証者は以下をしなければなりません（MUST）:

* 有効な証明書で HTTPS 上でのみ接続し、リダイレクトのフォローを拒否します（リダイレクトは宣言された位置を変える — エラーとして扱う）。
* 2 層ポリシーでレスポンスサイズを上限とします: `/.well-known/adagents.json` で提供されるポインターファイル（インラインか `authoritative_location` を運ぶか）は [一般 SSRF ボディ上限](/docs/building/by-layer/L1/security#webhook-url-validation-ssrf) の 5 MB を保ちます — パブリッシャーごとのポインターファイルは小さいはずで、5 MB は誤構成を捕捉します。`authoritative_location` をデリファレンスして到達する権威ファイル（2 番目のホップ）は、20 MB のより高い推奨上限を使います。なぜならそのオリジンはパブリッシャーネットワーク全体にファンアウトすることに明示的にオプトインしており、日常的に数千のプロパティまたはパブリッシャードメインを列挙する必要があるからです。両ホップで短い connect/read タイムアウト（各 ≤ 10s）を強制します。
* 5xx またはタイムアウトで、フェイルクローズするのではなく最大 24 時間、以前キャッシュされた権威ファイルを提供します。一時的な CDN 障害は失効ではありません。
* 少なくとも 24 時間ごとにリフレッシュを試みます。繰り返しの 5xx レスポンスはキャッシュを延長してはなりません（MUST NOT） — 7 日絶対上限は、任意の種類の最新のレスポンスからではなく、最新の成功したフェッチから測定されます。
* オリジンの `Cache-Control` にかかわらず、最新の成功したフェッチから 7 日でキャッシュ寿命を上限とします。その後、フェイルクローズします — ネットワークはオリジンを修正する 7 日を持っていました。
* 非単調な `last_updated`（リフレッシュされたファイルのタイムスタンプがキャッシュされたファイルより古い）を無効なレスポンス、5xx と同等として扱います: キャッシュを提供し、アラートし、古いファイルを採用しません。これは、攻撃者が以前失効したエージェントを再確立するため古いファイルを再提供するロールバック攻撃をブロックします。

**増分リフレッシュ（条件付きリクエスト）。** すべての消費者で単純にリフレッシュされる 20 MB の権威ファイルは両側で高価で、すべてのパブリッシャーチャーンを完全な再ウォークに変えます。権威ファイルオリジンは HTTP 条件付きリクエストをサポートすべきで（SHOULD）、検証者はそれらを使うべきです（SHOULD）:

* オリジンは、ファイル内容が変わるたびに再生成される `ETag` と `Last-Modified` ヘッダーを権威ファイルで発行すべき（SHOULD）。
* 検証者は、すべてのリフレッシュで `If-None-Match`（推奨）または `If-Modified-Since` を送り、`304 Not Modified` を「キャッシュは有効なまま、この成功から 7 日クロックを再開」として扱うべき（SHOULD） — キャッシュ寿命目的では成功したボディフェッチと同じ効果。
* `authorized_agents[]` ごとのオプションの `last_updated` フィールド（`adagents.json` スキーマを参照）は、消費者に部分ウォークインデックス化の 2 番目の軸を与えます: ファイルレベルの `last_updated` でキーされたインデックスを既に持つ検証者は、自身の `last_updated` がインデックス値より古い authorized-agents エントリーをスキップできます。これは助言的です — 消費者はそれを無視して完全なファイルを再インデックスしてもよい（MAY）。

条件付きリクエストは、スケールでのマネージドネットワークの部分更新プロトコルです。それらなしでは、週次でチャーンする 3,000 パブリッシャーを持つネットワークは、すべてのバイヤー側検証者にリフレッシュごとバイヤーごと 20 MB のダウンロードを強います。それらありで、定常状態コストは 1 ラウンドトリップと 304 です。

### Publisher revocation (the exit lifecycle)

`publisher_properties[].publisher_domains[]` からパブリッシャードメインを削除するだけでは不十分です — 下流検証者のキャッシュされた権威ファイルは、去ったパブリッシャーを最大 7 日キャッシュ上限まで認可し続けます。次のリフレッシュで伝播する必要がある失効（紛争でネットワークを去るパブリッシャー、コンプライアンス問題、誤構成クリーンアップ）には、権威ファイルはトップレベルの `revoked_publisher_domains[]` 配列に `revoked_at` タイムスタンプでパブリッシャーをリストしなければなりません（MUST）。

検証者の動作:

* 検証者は、`revoked_publisher_domains[]` の任意のパブリッシャードメインを、同じドメインが依然として任意の `authorized_agents[].publisher_properties[].publisher_domain` / `.publisher_domains[]`、`authorized_agents[].properties[].publisher_domain`（`inline_properties` 認可タイプ）、またはファイル内の他の場所のトップレベル `properties[].publisher_domain` に現れるかどうかに **かかわらず**、もはや認可されていないものとして扱わなければなりません（MUST）。失効リストが優先します — これはネットワークがすべてのセレクターエントリーを再デプロイせずに失効を出荷できるようにします。
* ファイルのキャッシュされた以前バージョンを持つ検証者は、エントリーの `revoked_at`（キャッチアップエントリーでは過去でありうる）ではなく、検証者の `last_updated` 採用時点で失効を適用しなければなりません（MUST）。
* **検証者側の追加のみ耐久性。** 検証者が `revoked_publisher_domains[]` エントリーで一度でも観測した `publisher_domain` は、後続のフェッチでエントリーが欠けていても、**検証者がそのドメインについて観測した最も早い `revoked_at` から 7 日** 失効として保持されなければなりません（MUST）。耐久性は `publisher_domain` のみでキーされます — `(publisher_domain, revoked_at)` タプルでキーすると、攻撃者がわずかに変異した `revoked_at`（例えば 1 秒早い）で同じドメインを再発行し、検証者が観測したことのない「新鮮な」タプルを提示し、保持をバイパスできます。`revoked_at` はクロック原点を設定するためだけに使い、耐久性キーの識別には使いません。これは耐久性をネットワークの保持 SHOULD ではなく検証者のキャッシュ状態に置き、ロールバックギャップを閉じます: `revoked_publisher_domains[]` を削除し `last_updated` を進めた古いファイルを再提供する攻撃者は、検証者の 7 日ウィンドウ内で以前失効したパブリッシャーを再確立できません。現在のフェッチで初めて見られる新しい失効（以前の観測なし）は、今から 7 日クロックを開始します。
* **再起動間の永続性。** 検証者は観測された失効エントリー（`{publisher_domain, earliest_revoked_at, first_observed_at}`）を耐久ストレージに永続化すべきです（SHOULD）。7 日ウィンドウ内で再起動するメモリ内のみの検証者は、以前の観測の記録がないためロールバックされたファイルを受け入れるかもしれません（MAY）。オペレーターはこれを既知の制限として扱い、インデックスを永続化するか残余リスクを受け入れるべきです（SHOULD）。7 日ウィンドウは、プロセス開始からではなく *検証者の* 最初の観測から測定されます。
* ネットワークは、初回出現中にエントリーを観測しなかった検証者が次のリフレッシュで依然としてそれを拾えるよう、各 `revoked_publisher_domains[]` エントリーを `revoked_at` の後少なくとも 7 日保持すべきです（SHOULD）。

マルチパブリッシャー退出または通常の商業関係終了下の日常チャーンには、ネットワークは `reason: "relationship_ended"` を使うべきで（SHOULD）、検証者の変更検出が日常失効のアラートを抑制し残りをレビューにルーティングできるようにします。

**以前失効したパブリッシャーの再認可。** `revoked_until` フィールドも un-revoke 動詞もありません。再認可するには、ネットワークは、`revoked_at` から検証者側 7 日耐久性ウィンドウが経過した *後* に `revoked_publisher_domains[]` からエントリーを削除します。より早くエントリーを削除することは、元の失効を観測した検証者では no-op です（彼らはウィンドウの残りの間ローカルで失効を保持します）。同週の再確立が運用上要求される時間制限付きコンプライアンスプルには、失効を `reason: "compliance_violation"` として実行し帯域外で再確立を調整することを優先します。スキーマは意図的にネットワークに 7 日前の再認可バックドアを与えません。それはロールバック攻撃と同じ表面になります。

**失効エントリーの拡張フィールドは規範的効果を持ちません。** `revoked_publisher_domains[]` アイテムはプロジェクト全体の `additionalProperties: true` ポリシーを使いますが、検証者はこれらのエントリーの未知のフィールドを無視しなければなりません（MUST） — 拡張は失効セマンティクスを緩めたりサイドチャネル再確立シグナルを運んだりできません。

**伝播レイテンシー。** `(agent, publisher_domain)` でキーされたメモリ内認可インデックスを維持する検証者は、`revoked_publisher_domains[]` にパブリッシャーをリストする `adagents.json` を検証者が *成功して* 再フェッチした後、1 クロール間隔を超えてペアを認可し続けてはなりません（MUST NOT）。上のフェッチセマンティクスからのキャッシュ制限された古さ（5xx での 24 時間フォールバック、7 日絶対上限）が適用されます — 境界は、任意の壁時計時間ではなく最新の成功したフェッチに対して保持されます。クロールバックログと中間 CDN キャッシングは実際のレイテンシーを延ばします。要件はネットワークではなく検証者自身のパイプラインにあります。

検証者はまた、次のクロールサイクルだけでなく **マニフェスト取り込み中に同期的に** 失効を適用すべきです（SHOULD）: `revoked_publisher_domains[]` が *任意の* パブリッシャードメインをリストする任意の `adagents.json` を採用するとき — 検証者が現在そのために任意のエージェントを認可するかどうかにかかわらず — 検証者は次の認可決定を提供する前に、そのパブリッシャーについて保持するすべての `(agent, publisher_domain)` エントリーをメモリ内インデックスから削除すべきです（SHOULD）。これは上の追加のみ耐久性ルールと合成し、置き換えません: メモリ内インデックス更新がライブクエリを新鮮に保つもので、7 日保持がロールバック攻撃を生き延びるものです。

**リファレンス実装（非規範的）。** 他の検証者は上の要件を異なるメカニズムで満たしてもよい（MAY）。このリポジトリのチェーンは: (a) ライターの失効ブランチが一致するカタログ行を退役させる。(b) 次のクロールパスがカタログから `(agent, publisher_domain)` セットを再スナップショットする（退役した行を除く）。(c) 前後の diff がドロップされた各ペアに `authorization.revoked` イベントを発行する。(d) レジストリ同期消費者がイベントをメモリ内インデックスに適用する。`authorization.revoked` イベント形状はリファレンス実装の語彙で、規範的なワイヤー形式ではありません。

**変更検出。** 1 つのデプロイがすべてのパブリッシャーに影響するため、バイヤーエージェントと検証者は以前の権威ファイルを保存し各リフレッシュで diff し、外れ値の変更でアラートすべきです（SHOULD）。パートナーが初日に実装できる具体的なデフォルトしきい値: 以前のフェッチに存在しなかった新しく追加された任意の `authorized_agents` エントリー、任意の委譲タイプダウングレード（例えば `exclusive` エントリーが非排他的になる）、10% または絶対 50 プロパティを超える任意のプロパティ数減少、`authoritative_location` 自体への任意の変更。そこからチューニングします — 目標は日常更新を抑制することではなく、支出をルーティングする前に侵害されたデプロイを捕捉することです。

**ポインター整合性（パブリッシャーごとのスワップ脅威）。** 上の *検証者フェッチセマンティクス* と *変更検出* ルールは、ネットワーク側の権威ファイルとオリジンの侵害を防御します。それらは単一のパブリッシャーのエッジでの *ポインターファイル自体* の侵害を防御しません。1 つのパブリッシャーの `/.well-known/adagents.json` への書き込みアクセスを得た攻撃者 — そのパブリッシャーの CDN コントロールプレーン、オリジンストレージ、または DNS 経由 — は、`authoritative_location` を攻撃者制御の URL に黙って変更できます。攻撃者がパブリッシャーのドメインが解決するインフラから提供しているため、その URL の TLS は有効で、サイズ/リダイレクト/タイムアウト上限はトリガーされず、変更は検証者に正当な委譲ハンドオフとして読まれます。

この最後の性質がポインタースワップを汎用整合性失敗と区別するものです: `authoritative_location` パターンの全ポイントは、パブリッシャーが委譲する場所を変更 *できる* ことなので、検証者は正当な委譲ハンドオフを壊さずに任意のポインター変更を敵対的として扱えません。ネットワーク CDN 脅威は広く浅い（1 つの侵害、すべてのパブリッシャーがハイジャック）。ポインタースワップ脅威は狭く深い（1 つのパブリッシャーがハイジャック、しかしネットワークが監視できない表面を通じて）。両方が範囲内です。

検証者は、変更された `authoritative_location` を日常リフレッシュではなく高重大度イベントとして扱わなければなりません（MUST）。具体的には:

* 検証者は変更された `authoritative_location` を自動採用してはなりません（MUST NOT）。変更が確認中の間、以前キャッシュされた権威ファイル（上の 7 日上限に従う）を提供し続けます。これは最小規範的フロアです。下の SHOULD が確認がどう得られるかを指定します。
* 検証者は、(a) 帯域外確認 — オペレーター承認、パブリッシャーサポートチャネル通知、またはアナウンスされたネットワーク移行 — または (b) 新しいポインター値が変わらないままでなければならない最小 24 時間の安定性猶予ウィンドウのいずれかの後にのみ新しい位置を尊重すべきです（SHOULD）。24h ウィンドウは未確認パスのフォールバックです。数分で完了する帯域外確認は (a) を満たし準拠します — 検証者は OOB パスに 24h フロアを課してはなりません（MUST NOT）。
* (a) の「アナウンスされたネットワーク移行」は、検証者オペレーターが検証できるパブリッシャー証明またはネットワーク証明の声明（例: 既存の信頼された鍵で副署名された署名付きアナウンス、パブリッシャーの `brand.json` `agents[]` セットへのオペレーター検証済み更新、またはオペレーターがそのパブリッシャーについて既に信頼する確立されたパブリッシャーアイデンティティチャネルの通知）を意味します。ブログ投稿やプレスリリースそれ自体は資格を持ちません。バーは公開性ではなく検証可能性です。
* 検証者は、候補権威ファイルを、公開されているときパブリッシャーの `/.well-known/brand.json` に対してクロスチェックすべきです（SHOULD）。`brand.json` が `agents[]` を宣言する場合、候補権威ファイルの `authorized_agents[]` URL は `brand.json` エージェントセットと照合されるべきです（SHOULD）。パブリッシャー自身のアイデンティティ宣言に不在のセールスエージェントを認可する権威ファイルは、ポインター侵害の強いシグナルで、オペレーターレビュー保留で採用をブロックすべきです（SHOULD）。正当なネットワーク間移行中、`brand.json` `agents[]` セットはポインター変更に遅れうる。`brand.json` の `last_updated` がポインターファイルの `last_updated` より古いとき、`brand.json`/権威の不一致を *権威矛盾* ではなく *古いクロスチェック* として扱い、移行を確認するため上のパス (a) または (b) にフォールバックします。
* 混合シグナルでは採用を拒否します: 候補権威ファイルの `last_updated` 退行と一致するポインター変更、ドメイン全体の委譲タイプダウングレード、またはエコシステム履歴のない初見のセールスエージェントは、採用ではなくキャッシュを保持しアラートする根拠です。このルールでは、*退行* は候補ファイルの `last_updated` がキャッシュされたファイルの `last_updated` より、小さなクロックスキュー許容（推奨: 60 秒）を超えて厳密に早いことを意味します。複数のエッジから提供されるポインターファイルは、通常運用で軽微な非単調性を観測できます。退行チェックはロールバック攻撃のためで、クロックジッターのためではありません。

自身のポインターファイルを管理するパブリッシャーは、他のパブリッシャーアイデンティティ表面（`/.well-known/brand.json`、DNS レコード、TLS 証明書発行）と同じインフラと変更管理制御からそれを提供すべきです（SHOULD）。ポインターファイルはアイデンティティ宣言です。それを静的マーケティングアセットとして扱うことが、スワップ脅威を実用的にする誤構成です。

**関係終了。** ポインターファイルパターンは、ネットワークがパブリッシャー DNS またはエッジを制御することに依存します。関係が終わるとき、委譲の両側が一緒に取り下げられなければなりません:

* ネットワークは、既に DNS/エッジ制御を失っていても、終了時に権威ファイルの `properties` からパブリッシャーを削除しなければなりません（MUST）。一致するプロパティのない元ネットワークのファイルを依然として指すパブリッシャーは [orphaned pointer](#orphaned-pointer) になります — バイヤーに未認可として可視。
* 検証者は、キャッシュされた委譲に依存するのではなく、パブリッシャードメインが所有権を移転するとき再フェッチして再検証すべきです（SHOULD）。

**署名付きポインター（計画中）。** ポインタースワップギャップの完全な閉鎖には署名付きポインターメカニズムが必要です: ポインターファイルは、正準 `(authoritative_location, last_updated)` オブジェクトにわたるパブリッシャー制御のデタッチ署名を運び、公開鍵は帯域外にアンカーされます — `brand.json` でパブリッシャー証明、または将来の集中化されたパブリッシャー鍵レジストリ経由。署名プリミティブと鍵ディスカバリー/ローテーションモデルは合意された設計を必要とし、3.x 要件ではなく計画された AdCP 4.0 追加として追跡されます。4.0 ロールアウトを実行可能に保つため、今日ポインターファイルを公開する実装者はポインターオブジェクト形状を安定に保つべきです（SHOULD）: トップレベルオブジェクトは `authoritative_location` と `last_updated` のみを含むべきで（SHOULD）、追加のトップレベルフィールドなしで、デタッチ署名が後で兄弟フィールド（または `.sig` コンパニオンパス）で、その間に追加されたカスタムフィールドと衝突せずに運べるようにします。4.0 が到達するまで、上のオペレーター側制御が規範的ベースラインです — それらは署名付きポインターの強さに一致しませんが、ポインタースワップ攻撃のコストを日常 CDN 侵害のコスト以上に上げます。それが 3.x が正直に約束できることです。

## 次のステップ

* [adagents.json 技術仕様](/docs/governance/property/adagents) — 完全なスキーマリファレンス、認可パターン、検証動作
* [プロパティガバナンス概要](/docs/governance/property) — adagents.json がより広範なガバナンスモデルにどう適合するか
* [AdAgents.json Builder](https://agenticadvertising.org/adagents/builder) — インタラクティブ検証者とファイル作成者
* [@adcp/sdk](https://github.com/adcontextprotocol/adcp-client) — ネットワーク一貫性チェック付き TypeScript クライアントライブラリ
