Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions examples/line-item-audio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pricing:

commitment_bounds: { min_budget: 5000.00 }
commitment:
proposal_id: "examplepub-us-q4-2026-omni"
version: 1
basis: spend
amount: 60000.00
currency: USD
Expand Down
2 changes: 2 additions & 0 deletions examples/line-item-ctv.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pricing:

commitment_bounds: { min_budget: 25000.00 }
commitment:
proposal_id: "examplepub-us-q4-2026-omni"
version: 1
basis: spend
amount: 160000.00
currency: USD
Expand Down
2 changes: 2 additions & 0 deletions examples/line-item-display.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pricing:
commitment_bounds: { min_budget: 10000.00, max_budget: 500000.00 }

commitment:
proposal_id: "examplepub-us-q4-2026-omni"
version: 1
basis: spend
amount: 80000.00
currency: USD
Expand Down
5 changes: 5 additions & 0 deletions spec/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ issue that caused it, so the comment record and the spec history line up.

## [Unreleased]

- § 4.1, § 5.6.1 — commitments carry `proposal_id` and `version`; a new
attempt on a stale version, or past `valid_until` or `price_valid_until`, is
rejected, and a replay returns the stored result. Breaking
([#24](https://github.com/IABTechLab/OpenProposal/issues/24)).

## [3.0-draft-1] — 2026-09-22

Initial draft published for public comment. Ported from the working-group
Expand Down
26 changes: 22 additions & 4 deletions spec/openproposal-3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ items.
| Field | Type | Mutability | Description |
| :--- | :--- | :--- | :--- |
| `proposal_id` | String | immutable | Unique identity for the proposal object |
| `version` | Integer | derived | Monotonically increasing revision number |
| `version` | Integer | derived | Monotonically increasing revision number. Each revision while status is `published` increments it |
| `seller_id` | String | immutable | IAB Tech Lab registry reference |
| `seller_name` | String | immutable | Canonical legal seller entity name, from the registry |
| `type` | Enum | immutable | `standard` \| `custom` |
Expand Down Expand Up @@ -288,6 +288,8 @@ when status becomes `agreed`.

| Key | Required | Meaning |
| :--- | :--- | :--- |
| `proposal_id` | REQUIRED | The proposal the commitment is made against |
| `version` | REQUIRED | The proposal `version` the commitment was priced against |
| `basis` | REQUIRED | `spend` \| `units` |
| `amount` | REQUIRED | The figure committed |
| `currency` | REQUIRED when `basis = spend` | ISO-4217 |
Expand All @@ -296,8 +298,22 @@ when status becomes `agreed`.
| `derived_units` | derived | Computed from `amount`, `agreed_rate` and `cost_method`. Informative, not binding |
| `idempotency_key` | REQUIRED | Buyer-generated, unique per commitment attempt |

A request carrying an `idempotency_key` already seen MUST return the original
result and MUST NOT create a second commitment.
An `idempotency_key` is opaque and scoped to one buyer and seller pair. The
seller MUST NOT interpret it.

The seller MUST reject a new commitment attempt whose `version` is not the
current version of the proposal named by `proposal_id`, whose proposal is past
`valid_until`, or whose `pricing[].price_valid_until` has passed. The rejection
MUST return the current version number, so the buyer can fetch it again. These
checks MUST be deterministic, as for `idempotency_key`.

For a replay from the same buyer of a commitment attempt the seller has
already processed, with the same `idempotency_key` and the same commitment
terms, the seller MUST return the original result and MUST NOT create a second
commitment. The version and expiry checks apply to a new attempt, not to
returning a stored result. Reusing an `idempotency_key` with different
commitment terms MUST produce an explicit conflict and MUST NOT create or
modify a commitment.

#### 5.6.2 hold_status

Expand Down Expand Up @@ -369,7 +385,9 @@ buyer commitment, and `settable` bounds. See

### 6.3 CTV line item

See [`examples/line-item-ctv.yaml`](../examples/line-item-ctv.yaml).
Shows a buyer commitment naming the `proposal_id` and `version` it was priced
against (§ 5.6.1). See
[`examples/line-item-ctv.yaml`](../examples/line-item-ctv.yaml).

### 6.4 Audio line item

Expand Down
Loading