Skip to content

[Change] § 2, § 4.1, § 5.1 — Add #33's ext container: keyed by domain, ignored when unknown, kept in the agreed record #131

Open

Description

@KonstantinMirin

What kind of change?

Add a new field

Which section?

Whole document / more than one section

Current text

n/a — new field. Related text, unchanged:

§ 2: A field on a line item MUST NOT inherit its value from the proposal or
from a sibling line item.

Proposed text

Our errors and extensions PR carries this text. The § 4.4 row and the change_requests[] wording come with that table in our post-agreement PR. It builds on the § 2.2 shared types and section numbers of our shared types PR, which also removes catalog_ref.

§ 2.2, add a row to the shared types:

| `Ext` | `Map[Domain, Object]` | The extension container. § 2.5 states its rules |

§ 4.1 and § 5.1, add a row to each table:

| `ext` | Ext | OPTIONAL | seller-set | See Extensions (§ 2.5) |

§ 4.4, add a row to the `ChangeRequest` keys:

| `ext` | Ext | OPTIONAL | See Extensions (§ 2.5) |

### 2.5 Extensions

The proposal, each line item, and each `change_requests[]` entry (§ 4.4) MAY carry
`ext`, an `Ext`. Each key MUST be a `Domain` that its owner controls, and each value
is an object that the owner defines. A seller's own entries MUST use its
`seller.domain` as the key.

    ext:
      examplepub.example: { placement_code: "BD-ROS-300x250-Q4" }

- An `ext` entry MUST NOT change the meaning of a field this specification
  defines. A term the counterparty must understand to transact MUST NOT be an
  `ext` entry; it is a field or a vocabulary term.
- A receiver MUST ignore an `ext` entry it does not understand, and MUST NOT
  reject a document because of it. It MUST keep `ext` unchanged when it
  stores or forwards the document.
- In an object whose keys this specification lists, a key outside `ext` that
  it does not list is invalid. An object whose content another definition
  sets, such as a `FormatSpec`'s `spec` (§ 5.4), is unaffected, and so are the
  open objects `DocumentRef` (§ 2.2), `ErrorObject` (§ 2.4), and `CostParameters`
  (§ 5.6.5).
- On the proposal and a line item, `ext` is part of the Full Representation and
  of the record frozen at `agreed` (§ 4.1.1), and a seller change to it is a
  revision. On a `change_requests[]` entry, it is outside the record, as the
  entry is (§ 4.4).
- Apart from an unknown term (§ 2.2), a receiver MAY skip a whole line item it
  cannot read, without assenting to it. It MUST NOT keep a line item after removing
  fields from it.

Why

@VJAlkimi's unknown-key comment (#33) found the gap: no rule says what a parser does with a key the draft doesn't define. A strict parser rejects a seller's placement code, a lenient one drops it, and the two agreed records differ. Of #33's two answers, we take the second: ext, kept unchanged and frozen at agreed, with undefined keys invalid elsewhere. We add domain keys and a no-override rule.

Implementers already need it. IAB Tech Lab's reference seller agent adds ext to its line item on its unmerged feat/openproposal-mapping branch. Its Google Ad Manager mapper keeps fields with no OpenProposal home there. Yet its line-item model, in @jaanijuk's test, silently drops six undefined fields.

OpenRTB 2.6, § 2.9, AdCOM 1.0, OpenDirect 2.1, and the Deals API 1.0 all carry ext. OpenRTB leaves it unstructured, so two vendors can pick the same key. A Domain key names the owner, as in an extension vocabulary term, so one owner names its terms, ext entries, and error codes.

A proposal binds, so it needs rules a bid request doesn't:

  • No override. Ignoring an entry is safe only if it can't change the agreed terms. A term the buyer must understand is a field, or a vocabulary term whose unknown value makes its entry unavailable or skips the line item.
  • Keep it. ext is inside the binding record of our binding-record change request (#63). An intermediary that strips an entry changes record_digest, and the seller rejects the commit with record_mismatch.
  • Frozen at agreed. An id assigned later, such as an ad server's line id, goes in external_references[] (§ 5.10), outside the record.

Details: Extensions: full rationale and examples

Knock-on effects

Open questions for the working group

  1. Should an ext key be a domain (examplepub.example), as proposed, or a reverse-DNS key per entry (com.examplepub.placement_code), as #33 writes it? Either way, one form should serve vocabulary terms, ext keys, and extension error codes.
  2. Answered in part in our errors and extensions PR: How does a receiver built to one release read a later release that adds keys? spec_version is REQUIRED on the proposal and inside the record, so each document names its release, as the well-known manifest of @Kishore-2572 (PR #76) does. Still open: what a receiver does with what its release doesn't list. It could reject an unknown major release. Within a major release, it could ignore unknown keys, as OpenRTB 2.6, § 2.6 does, and also keep them. The second option weakens the no-override rule. The PR asks this in § 8, and the rules issue lists both rules.
  3. Answered in part in our errors and extensions PR: Should ext also go on other objects? Each change_requests[] entry, which our post-agreement PR adds, carries one, outside the record. Still open: a pricing[] entry, commitment, or a negotiation_history[] entry. The reference seller agent puts one on its history entry. OpenRTB 2.6 and AdCOM 1.0 allow it on any object. Each holder needs a marker and a binding-record rule.
  4. Answered in part by @jaanijuk: Should an entry be able to require that a receiver understand it? VAST 4.3, § 3.18 requires that of every extension, and JWS crit (RFC 7515, § 4.1.11) allows it per header. They propose that a binding ext term need explicit acceptance before agreed, or the line item is rejected. One mechanism is a list of keys the receiver must understand, like crit. Informational entries, such as ext.gam, are ignored, as proposed. Still open: whether the working group wants that list, or the no-override rule, which keeps binding terms out of ext.
  5. Answered in part in our shared types PR: May a summary in § 2.1, and so a manifest entry under PR #76, carry ext, so that screening agents see an entry? A summary is a strict path subset of the full object, and its list has no ext path. Still open: whether screening agents need one.
  6. Should the AAMP hub state one extension rule for OpenProposal and the primitives? The primitives use ext as the single extension slot, reserve x_, and drop what they don't know on re-serialization. This change request keys ext by domain and keeps it.

Would this break an implementation already built to this draft?

No — additive or editorial

Alternatives you considered and rejected

You are commenting as

Other — IAB Tech Lab member (Postindustria).

Before you submit

  • I have read CONTRIBUTING.md and agree my contribution may be published under this repository's licence.
  • This contains no confidential or commercially sensitive information.

Revised 2026-11-03: Rewritten to match our errors and extensions PR. Open questions 2, 3, and 5 are answered in part.

Analyzed and generated with the help of Claude, fully reviewed by me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions