Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/metric-qualifier-vendor-symmetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"adcontextprotocol": minor
---

Fix the vendor-scope qualifier on `delivery-metric-aggregate` (previously a closed object with no properties, so only `{}` could validate) and add the optional 5-key qualifier to the vendor branches of `committed-metric` and `missing-metric`, matching what `canonical-reporting-commitment` already allows — vendor metrics measured under different attribution windows or methodologies are now distinguishable on the contract and reconciliation surfaces. A qualifier parity contract test now enforces an identical closed key set across every hand-maintained copy.
4 changes: 2 additions & 2 deletions docs/building/by-layer/L1/security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ Implementations MUST keep three layers distinct:
2. **Credential** — the issuer-signed claim found through the reference or supplied as an embedded proof.
3. **Evaluation** — the receiving seller's or governance agent's result after applying its trust policy.

<!-- Using latest because these schemas are not yet released in any version.
Update to the correct version alias after the next release. -->
{/* Using latest because these schemas are not yet released in any version.
Update to the correct version alias after the next release. */}
The shared schemas are [`attestation-reference.json`](https://adcontextprotocol.org/schemas/v3/core/attestation-reference.json), [`attestation-issuer.json`](https://adcontextprotocol.org/schemas/v3/core/attestation-issuer.json), [`attestation-subject.json`](https://adcontextprotocol.org/schemas/v3/core/attestation-subject.json), and [`attestation-evaluation.json`](https://adcontextprotocol.org/schemas/v3/core/attestation-evaluation.json).

Every presentation identifies an issuer, an open URI-namespaced `claim_type`, a typed subject, and at least one delivery path:
Expand Down
4 changes: 2 additions & 2 deletions docs/building/operating/transport-errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,8 @@ JSON Schemas for all recommended `details` shapes are published alongside the er
- [`/schemas/v3/error-details/rate-limited.json`](https://adcontextprotocol.org/schemas/v3/error-details/rate-limited.json)
- [`/schemas/v3/error-details/budget-too-low.json`](https://adcontextprotocol.org/schemas/v3/error-details/budget-too-low.json)
- [`/schemas/v3/error-details/audience-too-small.json`](https://adcontextprotocol.org/schemas/v3/error-details/audience-too-small.json)
<!-- Using latest because account-moved.json is not yet released in any version.
Update to the correct version alias after the next release. -->
{/* Using latest because account-moved.json is not yet released in any version.
Update to the correct version alias after the next release. */}
- [`/schemas/latest/error-details/account-moved.json`](https://adcontextprotocol.org/schemas/latest/error-details/account-moved.json)
- [`/schemas/v3/error-details/account-setup-required.json`](https://adcontextprotocol.org/schemas/v3/error-details/account-setup-required.json)
- [`/schemas/v3/error-details/creative-rejected.json`](https://adcontextprotocol.org/schemas/v3/error-details/creative-rejected.json)
Expand Down
2 changes: 2 additions & 0 deletions docs/media-buy/task-reference/create_media_buy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ When `confirmed_at` is `null`, sellers MUST omit `packages[].committed_metrics`.
- **`attribution_window`** — when `metric_id` is an outcome metric and the seller commits to a specific lookback window, the entry SHOULD carry `qualifier.attribution_window` as a structured duration (`{ interval: 14, unit: "days" }`). Two outcome rows over different windows are reported as separate rows so buyers don't accidentally aggregate across periods.

Without the qualifier, the contract is ambiguous and reconciliation falls back to whatever the delivery report happens to carry. The qualifier vocabulary is closed (`additionalProperties: false`); new keys ship explicitly in subsequent minors.

Vendor-scope entries MAY carry the same qualifier keys when the same vendor metric is committed under more than one methodology or window — e.g., `attribution_window` on a vendor outcome metric distinguishes a 14-day vendor attribution commitment from a 30-day one for the same `(vendor, metric_id)`. `missing_metrics` mirrors the qualifier for vendor entries exactly as it does for standard entries.
- **Reconciliation:** `missing_metrics` on [`get_media_buy_delivery`](/docs/media-buy/task-reference/get_media_buy_delivery) filters `committed_metrics` to entries where `committed_at < reporting_period.end`, then flags any that aren't populated in the report. A metric committed mid-flight is only audited from its commitment timestamp forward. Qualifiers are matched verbatim — a committed `{viewable_rate, mrc}` is not satisfied by a delivered `viewable_rate` carrying `viewability.standard: groupm`.
- **Optional in v1.** Sellers without per-package snapshot infrastructure can adopt incrementally. Absence is conformant but carries a known audit gap: without the snapshot, `missing_metrics` reconciles against the product's live `available_metrics` at report time, which may not reflect what was committed at create time. Sellers that omit `committed_metrics` accept this risk; buyers SHOULD treat absence as "no audit-grade contract" rather than "clean delivery." Expected to become required at the next major.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"deploy:cdn-artifacts-cutover:dry-run": "wrangler deploy --config workers/artifact-cdn/wrangler.cutover.toml --dry-run",
"verify:cdn-artifacts-cutover": "node scripts/verify-cdn-artifacts-cutover.mjs",
"typecheck": "tsc --project server/tsconfig.json --noEmit",
"test:schemas": "node tests/schema-validation.test.cjs && node --test tests/trusted-match-offer-creative-data.test.cjs tests/accessibility-violation-details.test.cjs tests/portfolio-routing-scope.test.cjs tests/catalog-item-availability-updates.test.cjs tests/schema-deprecation-metadata.test.cjs tests/creative-rotation.test.cjs tests/metric-identity-coherence.test.cjs tests/lint-schema-enum-drift.test.cjs tests/synthetic-depiction.test.cjs && npm run test:geo-region-targeting",
"test:schemas": "node tests/schema-validation.test.cjs && node --test tests/trusted-match-offer-creative-data.test.cjs tests/accessibility-violation-details.test.cjs tests/portfolio-routing-scope.test.cjs tests/catalog-item-availability-updates.test.cjs tests/schema-deprecation-metadata.test.cjs tests/creative-rotation.test.cjs tests/metric-identity-coherence.test.cjs tests/metric-qualifier-parity.test.cjs tests/lint-schema-enum-drift.test.cjs tests/synthetic-depiction.test.cjs && npm run test:geo-region-targeting",
"test:performance-feedback": "node --test --test-force-exit --test-timeout=30000 tests/performance-feedback-contract.test.cjs",
"test:dist-schema-version-ids": "node --test --test-force-exit --test-timeout=30000 tests/dist-schema-version-ids.test.cjs",
"test:examples": "node tests/example-validation-simple.test.cjs && npm run test:tmp-context-merge",
Expand Down
27 changes: 27 additions & 0 deletions static/schemas/source/core/committed-metric.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@
"$ref": "/schemas/core/vendor-metric-id.json",
"description": "Identifier for the metric within the vendor's vocabulary."
},
"qualifier": {
"type": "object",
"description": "Optional qualifier disambiguating commitments to the same vendor metric measured under different methodologies or windows. Same closed key set as standard-scope entries; new keys ship explicitly.",
"properties": {
"viewability_standard": {
"$ref": "/schemas/enums/viewability-standard.json",
"description": "Viewability standard for this vendor metric, as a closed enum."
},
"completion_source": {
"$ref": "/schemas/enums/completion-source.json",
"description": "Completion attestation source for this vendor metric."
},
"attribution_methodology": {
"$ref": "/schemas/enums/attribution-methodology.json",
"description": "Attribution methodology for this vendor outcome metric."
},
"attribution_window": {
"$ref": "/schemas/core/duration.json",
"description": "Attribution window for this vendor outcome metric, as a structured duration."
},
"lift_dimension": {
"$ref": "/schemas/enums/lift-dimension.json",
"description": "Brand-lift dimension for this vendor metric."
}
},
"additionalProperties": false
},
"committed_at": {
"type": "string",
"format": "date-time",
Expand Down
24 changes: 23 additions & 1 deletion static/schemas/source/core/delivery-metric-aggregate.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,29 @@
},
"qualifier": {
"type": "object",
"description": "Optional qualifier keys for vendor metrics that need disambiguation (rare today — most vendor methodologies are intrinsic to the metric definition).",
"description": "Optional qualifier keys disambiguating this vendor-metric row from sibling rows under the same (vendor, metric_id) — e.g., attribution_window on a vendor outcome metric. Same closed key set as the standard branch; new keys ship explicitly.",
"properties": {
"viewability_standard": {
"$ref": "/schemas/enums/viewability-standard.json",
"description": "Viewability standard under which this row was measured. MRC and GroupM define materially different thresholds; never sum across standards."
},
"completion_source": {
"$ref": "/schemas/enums/completion-source.json",
"description": "Source of `completion_rate` attestation for this row — `seller_attested` from player/ad server, `vendor_attested` from a third-party measurement vendor. The two paths can yield different rates; never sum across sources."
},
"attribution_methodology": {
"$ref": "/schemas/enums/attribution-methodology.json",
"description": "Attribution methodology under which this outcome row was computed (`deterministic_purchase`, `probabilistic`, `panel_based`, `modeled`). Outcome metrics measured under different methodologies represent materially different numbers; never sum across methodologies."
},
"attribution_window": {
"$ref": "/schemas/core/duration.json",
"description": "Attribution window for this outcome row. Object-valued duration (`{interval, unit}`), not a shorthand string. Outcome metrics measured over different windows represent the same metric over different time periods; the partition keeps them as separate rows so buyers don't accidentally aggregate."
},
"lift_dimension": {
"$ref": "/schemas/enums/lift-dimension.json",
"description": "Brand-lift dimension this row represents (awareness, consideration, favorability, purchase intent, or ad recall). Required when `metric_id` is `brand_lift`. Each dimension is a separate surveyed outcome with its own sample size and confidence interval; never sum across dimensions."
}
},
"additionalProperties": false
},
"value": {
Expand Down
22 changes: 22 additions & 0 deletions static/schemas/source/core/missing-metric.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,28 @@
},
"metric_id": {
"$ref": "/schemas/core/vendor-metric-id.json"
},
"qualifier": {
"type": "object",
"description": "Mirrors the qualifier on the corresponding vendor-scope `committed_metrics` entry. MUST match that entry so reconciliation joins on (vendor, metric_id, qualifier).",
"properties": {
"viewability_standard": {
"$ref": "/schemas/enums/viewability-standard.json"
},
"completion_source": {
"$ref": "/schemas/enums/completion-source.json"
},
"attribution_methodology": {
"$ref": "/schemas/enums/attribution-methodology.json"
},
"attribution_window": {
"$ref": "/schemas/core/duration.json"
},
"lift_dimension": {
"$ref": "/schemas/enums/lift-dimension.json"
}
},
"additionalProperties": false
}
},
"required": [
Expand Down
Loading
Loading