Repository navigation
Open
Labels
change-requestProposes specific normative wordingProposes specific normative wordingnormativeChanges what the spec requiresChanges what the spec requiressection:4-proposalsection:5.6-commercial
Description
What kind of change?
Change a normative requirement (MUST / SHOULD / MAY)
Which section?
Whole document / more than one section
Current text
§ 4.1:
| `version` | Integer | derived | Monotonically increasing revision number |
§ 5.6.1: n/a, new keys.Proposed text
**§ 4.1, `version`:**
| `version` | Integer | derived | Monotonically increasing revision number. Each revision while status is `published` increments it |
**§ 5.6.1, two new keys:**
| `proposal_id` | REQUIRED | The proposal the commitment is made against |
| `version` | REQUIRED | The proposal `version` the commitment was priced against |
**§ 5.6.1, add after the idempotency paragraph:**
The seller MUST reject a commitment whose `version` is not the current
version, 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.
This check MUST be deterministic, as for `idempotency_key`.
**§ 4.1, `negotiation_history[]`:** no change to the row. Entries already carry `version`.
**§ 6, example commitment:**
commitment:
proposal_id: "examplepub-us-q4-2026-omni"
version: 4
basis: spend
amount: 160000.00
currency: USD
flight_start: "2026-10-06"
flight_end: "2026-12-21"
idempotency_key: "agency-a-camp1-weather-app-ctv-3b7e0d52"Why
§ 4.1 already has version, derived and monotonic, but nothing says a commitment must name the version it was priced against, or what happens if the buyer's copy is stale. A buyer agent that cached an old version could commit at old terms.
Raised on the working calls: track by proposal_id and version, given the risk of buyers holding expired versions.
Out of scope: per-version performance statistics (served, inquiries, win rate) are the seller's private analytics in its proposal store, not object fields.
Knock-on effects
- § 4.1: the
versiondescription states that each revision while published increments it. - § 5.6.1: two REQUIRED keys and the rejection rules.
- Appendix A / B: reviewed; the new keys sit within
commitment, so no new rows. - § 6: an example commitment showing
proposal_idandversion. - Breaking: a commitment without
proposal_idandversionwould be rejected.
Would this break an implementation already built to this draft?
Yes — breaking
Alternatives you considered and rejected
- Accepting a stale commitment at current terms: the buyer would commit to terms it did not see.
You are commenting as
Standards body / working group participant
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.
Reacted by dtbarne
Metadata
Metadata
Assignees
Labels
change-requestProposes specific normative wordingProposes specific normative wordingnormativeChanges what the spec requiresChanges what the spec requiressection:4-proposalsection:5.6-commercial
Activity
aleksUIX commentedon Oct 14, 2026
Could the version and expiry checks explicitly exclude replay of an already processed commitment?
Section 5.6.1 currently requires a previously seen
idempotency_keyto return the original result. Suppose the seller accepts a commitment immediately beforeprice_valid_until, but the response is lost. The buyer retries the identical request after that time. The existing rule requires the accepted result; the proposed expiry rule requires rejection.Suggested addition:
For an authenticated replay of the same previously processed commitment attempt, the seller MUST return the original result without creating another commitment. The current-version and expiry checks apply to a new attempt, not to returning a stored result. Reusing the same idempotency key with different commitment terms MUST produce an explicit conflict and MUST NOT create or modify a commitment.
This preserves rejection of new stale commitments while allowing a buyer to recover the outcome of a timed-out request. The same distinction applies when the current published version changes between acceptance and retry.
This is a source-review counterexample, not a defect reproduced in an implementation.
Commenting in a personal capacity.
KonstantinMirin commentedon Oct 22, 2026
Postindustria (IAB Tech Lab member) supports pinning the
versiona commitment is made against, and @aleksUIX's replay distinction. Two gaps remain. #24 makes everyseller-setrevision (§ 3) incrementversion, so correcting one line item rejects commitments on another. And an equalversiondoesn't prove equal bytes (#35). Our coming PRs close both.Bind content, not the counter. The buyer's
commitmententry inassent[]carriesversionandrecord_digest, the digest of the binding record of the line items it names (our binding-record filing). The seller recomputes it over those line items as it stores them, plus the buyer's writes. An equal value means the buyer read the same terms, so the seller MAY accept at the entry'sversion. Our PR on what is signed states this test, and our lifecycle PR defines staleness the same way.sequenceDiagram Seller->>Buyer: version 4, line items A and B Note over Seller: seller revises, version 5 Buyer->>Seller: commit on A at version 4, with record_digest Note over Seller: recompute over stored A plus the writes alt equal Seller-->>Buyer: MAY accept at version 4 else A changed Seller-->>Buyer: rejected (stale_version) else buyer read other bytes Seller-->>Buyer: rejected (record_mismatch) endOne replay rule. #73 states it in line with the replay rule in IAB's agentic primitives (FD-12), and our PR on what is signed keeps it. A replay under the same key gets the result as it stands, without re-running the checks. A changed
Commitunder that key getsidempotency_conflict, a code our errors and extensions PR defines.Take
idempotency_keyand the pin out ofcommitment. Both describe onecommit, not terms. Our PR on what is signed puts them on the buyer'sassent[]entry, outside the digest.Details: Commitment digest and replay: full rationale and examples
Open questions:
assent[], but a rejection writes no entry, so the seller keeps it apart. @EvgenyAndroid suggests on #128 a floor atvalid_until(offer_window.endin our PRs). Our PRs leave replay beyond § 5.6.1 to the AAMP wire and lifecycle contract (§ 1.2). Should that contract set this floor?Revised 2026-11-03: Rewritten against our coming PRs: the seller's own recompute replaces
offer_digest, andidempotency_keymoves to theassent[]entry. We withdraw thevalid_untilfloor our #128 reply quoted, pending open question 1.Analyzed and generated with the help of Claude, fully reviewed by me.
Kishore-2572 commentedon Oct 22, 2026
Thanks @aleksUIX. As the filer, I agree that the version and expiry checks should apply to a new commitment attempt, not to replaying the stored result of one already processed. Otherwise a buyer cannot recover the outcome of a timed-out request. I will include your suggested wording in the draft PR for this change request, including the explicit conflict when the same
idempotency_keyis reused with different terms, for the working group to consider at adjudication.Kishore-2572 commentedon Oct 22, 2026
Thank you, @KonstantinMirin. Three points in reply, as the filer:
iab-agentic-primitivesFD-12 and @aleksUIX's wording: keys are opaque and scoped per buyer/seller pair; the same attempt returns the stored result without re-running the version and expiry checks; the same key with a different body is rejected as a conflict.versionand so rejects a commitment on an unchanged line item.offer_digestis one fix, but it depends on the binding record in [Change] § 4.1 — Define record_digest and assent[]; defer signer identity to the AAMP profile #63, and per-line-item staleness ([Change] § 4, § 5.1 — Add § 4.3 Lifecycle: who moves each status #65) and what counts as a new version ([Change] § 4.1 — Freeze a version's offered terms; changes create version n+1 and a revised entry #64) bear on the same question. The draft PR will list these as knock-on effects for the working group rather than adopt one here.idempotency_keyon the request: outside this change request's scope. The draft PR will note it as a related proposal.Scope the replay rule to the same buyer
Define the replay body and tighten the stale-version checks