diff --git a/examples/line-item-audio.yaml b/examples/line-item-audio.yaml index 4ca2f21..245e297 100644 --- a/examples/line-item-audio.yaml +++ b/examples/line-item-audio.yaml @@ -29,6 +29,7 @@ commitment: idempotency_key: "agency-a-camp1-streaming-audio-a7c33e10" committed_metrics: [{ metric: completion_rate, value: 0.92, basis: seller_reported }] +visibility: public buying_route: SSP_PLATFORM transaction_mechanism: { available: ["PREFERRED_DEAL"], included: ["PREFERRED_DEAL"] } serving_mode: dai diff --git a/examples/line-item-ctv.yaml b/examples/line-item-ctv.yaml index fda3994..d2eded9 100644 --- a/examples/line-item-ctv.yaml +++ b/examples/line-item-ctv.yaml @@ -29,6 +29,7 @@ hold_status: { hold_available: true, hold_duration: "P14D", hold_expires_at: "2026-10-01T00:00:00Z" } committed_metrics: [{ metric: completion_rate, value: 0.95, basis: seller_reported }] +visibility: public buying_route: SSP_PLATFORM transaction_mechanism: { available: ["PRIVATE_AUCTION"], included: ["PRIVATE_AUCTION"] } serving_mode: ssai diff --git a/examples/manifest.json b/examples/manifest.json new file mode 100644 index 0000000..7652e1f --- /dev/null +++ b/examples/manifest.json @@ -0,0 +1,67 @@ +{ + "seller_id": "reg:examplepub-digital", + "generated_at": "2026-10-01T06:00:00Z", + "spec_version": "3.0", + "proposals": [ + { + "proposal_id": "examplepub-us-q4-2026-omni", + "version": 1, + "seller_name": "Example Publisher US", + "description": "Cross-channel Example Publisher US package spanning display, in-stream video and CTV. Business and financial audience skew, weekday-heavy delivery.", + "valid_from": "2026-10-01T00:00:00Z", + "valid_until": "2026-12-31T23:59:59Z", + "full_url": "https://examplepub.example/openproposal/examplepub-us-q4-2026-omni", + "line_items": [ + { + "line_item_id": "weather-app-ctv", + "channel": "ctv", + "properties": [ + "weather-app" + ], + "formats": { + "included": [ + "ctv/instream-15s" + ] + }, + "pricing": { + "cost_method": "CPM", + "gross_rate": 45.0 + }, + "committed_metrics": [ + { + "metric": "completion_rate", + "value": 0.95, + "basis": "seller_reported" + } + ], + "transaction_mechanism": [ + "PRIVATE_AUCTION" + ] + }, + { + "line_item_id": "streaming-audio", + "channel": "audio", + "formats": { + "included": [ + "audio/produced-30s" + ] + }, + "pricing": { + "cost_method": "CPM", + "gross_rate": 18.0 + }, + "committed_metrics": [ + { + "metric": "completion_rate", + "value": 0.92, + "basis": "seller_reported" + } + ], + "transaction_mechanism": [ + "PREFERRED_DEAL" + ] + } + ] + } + ] +} diff --git a/spec/CHANGELOG.md b/spec/CHANGELOG.md index 1dfacef..a538687 100644 --- a/spec/CHANGELOG.md +++ b/spec/CHANGELOG.md @@ -5,6 +5,11 @@ issue that caused it, so the comment record and the spec history line up. ## [Unreleased] +- § 2.3 — a seller MAY publish its public standard line items as a static + manifest at `/.well-known/openproposal.json`, for a two-phase + discover-then-propose flow + ([#29](https://github.com/IABTechLab/OpenProposal/issues/29)). + ## [3.0-draft-1] — 2026-09-22 Initial draft published for public comment. Ported from the working-group diff --git a/spec/openproposal-3.0.md b/spec/openproposal-3.0.md index 6940958..100b5dc 100644 --- a/spec/openproposal-3.0.md +++ b/spec/openproposal-3.0.md @@ -110,6 +110,31 @@ example: "examplepub/audiences/smb-decision-makers@3" by its resolved value in the stored record, so the committed artifact is self-contained and immutable. +### 2.3 Publication + +A seller MAY publish `https:///.well-known/openproposal.json`. + +Contents: `{ seller_id, generated_at, spec_version, proposals[] }`, where each +entry in `proposals[]` carries `proposal_id`, `version`, the Summary +Representation (§ 2.1) of each line item, and a `full_url` for the second +phase. + +- `ETag` / `Last-Modified` are REQUIRED, so buyers can poll cheaply. +- Only standard proposals appear, and within them only line items whose + `visibility` (§ 5.8) is `public`. `registry_gated` and `named` line items do + not. +- Manifest entries MUST match the current version of each proposal. A stale + entry is a seller error. +- Property lists stay as names in the summary; large lists use `catalog_ref` + (§ 2.2). + +Two-phase flow: + +1. **Discover:** fetch the manifest and screen the summaries. No language model + is required. +2. **Propose:** fetch the Full Representation of shortlisted line items from + `full_url`, then compose and commit as usual. + --- ## 3. Field mutability @@ -375,6 +400,12 @@ See [`examples/line-item-ctv.yaml`](../examples/line-item-ctv.yaml). See [`examples/line-item-audio.yaml`](../examples/line-item-audio.yaml). +### 6.5 Publication manifest + +A manifest (§ 2.3) listing the public line items of the example proposal. The +display line item is `registry_gated`, so it is not listed. See +[`examples/manifest.json`](../examples/manifest.json). + --- ## 7. Why this split