You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Impl] commitment.idempotency_key has no scope, conflict rule or retention #128
An implementation that parses and validates OpenProposal proposals, line items and commitments end to end.
What you tried to express, and what happened
§ 5.6.1 says "A request carrying an idempotency_key already seen MUST return the original result and MUST NOT create a second commitment." Three things are left open:
Scope. Unique to what: the buyer, the seller, the proposal? Two buyers that pick the same string would collide.
Conflict. If the same key arrives with a different payload (a changed amount, say), returning the original result silently hides a real disagreement.
Retention. How long a seller must remember the key.
What you did instead
Scoped keys to buyer plus seller, returned a conflict error when a reused key carries a different payload, and declared a retention window.
Suggested resolution: scope the key (buyer plus seller, or plus line item), require a conflict error on a changed payload, and require the seller to state how long keys are retained.
Fields involved
commitment.idempotency_key
How blocking was it?
Workaround required, but it works
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 — no real rate cards, deal terms, client names or inventory data.
Retention: still open. Neither says how long a seller must keep a key and its result.
Suggested floor: the seller MUST keep each key and its result at least until the proposal's valid_until passes. Before then, a forgotten key turns a retry into a new attempt, and that attempt passes PR #73's version and expiry checks if the proposal hasn't changed. After valid_until, PR #73 rejects every new attempt, so a forgotten key can't produce a second commitment. The floor leaves one case open: a buyer that never saw the first response and retries after valid_until gets expired and still doesn't know whether it committed. A longer retention, or a way to look a commitment up by its key, would close that.
In our PRs, a commit that wrote an entry keeps its key in assent[], so its result lasts as long as the record. A rejection writes no entry, so § 5.6.1 says the seller MUST keep one whose retry isn't same at least until offer_window.end, which replaces valid_until, or, with no end, as long as it keeps the proposal. After that date, every new commit fails as expired.
Revised 2026-11-06: Your floor is back in our signing PR, after @pkanna000 asked for it too.
Analyzed and generated with the help of Claude, fully reviewed by me.
Implementation evidence in support of making @EvgenyAndroid's resolution normative in § 5.6.1 itself.
I read the IAB Tech Lab Agent Registry on 5 Nov 2026 (53 agents, 1,735 tool definitions, public read-only access). 52 tools across 25 agents commit or change spend: media buys, orders, campaigns. 20 of them publish an input schema, and 2 of those 20 accept anything resembling an idempotency key. Buying agents retry on timeouts automatically, so today most retried commitments have no protection beyond what § 5.6.1 will require. The reference seller agent has the same gap on POST /proposals: IABTechLab/seller-agent#131.
That argues for writing all three parts into § 5.6.1:
Scope: the key is unique per buyer identity + seller + proposal_id.
The same retry problem applies to hold requests: a hold retried after a timeout can take a second hold on the same inventory. If #143 lands, the same key rule would be worth applying there, and it pairs with the per-buyer cap in #156.
Thanks, @pkanna000, for the registry data. Our signing PR (#142) covers your first two parts. § 4.1.2 scopes the key to one buyer and seller pair, which is wider than one proposal_id. In § 5.6.1, reusing it with a different Commit returns idempotency_conflict and writes nothing.
For retention, that PR now sets @EvgenyAndroid's floor, which meets yours. A commit the seller doesn't reject writes the buyer's commitment entry, which carries the key, and assent[] keeps that entry for as long as the proposal exists. A rejection writes no entry, so the seller MUST keep one whose retry isn't same at least until offer_window.end, which replaces the draft's valid_until. In our holds PR (#143), a hold's valid_until can't pass that date (§ 4.3.4), so it's already the later of your two dates.
A retried hold can't take a second one. That PR says a repeated request while a hold is requested or held MUST NOT start a second hold.
Analyzed and generated with the help of Claude, fully reviewed by me.
Activity
EvgenyAndroid commentedon Oct 27, 2026
Where this stands after PR #73 and #130:
idempotency_conflict.Suggested floor: the seller MUST keep each key and its result at least until the proposal's
valid_untilpasses. Before then, a forgotten key turns a retry into a new attempt, and that attempt passes PR #73's version and expiry checks if the proposal hasn't changed. Aftervalid_until, PR #73 rejects every new attempt, so a forgotten key can't produce a second commitment. The floor leaves one case open: a buyer that never saw the first response and retries aftervalid_untilgetsexpiredand still doesn't know whether it committed. A longer retention, or a way to look a commitment up by its key, would close that.KonstantinMirin commentedon Oct 27, 2026
Thank you, @EvgenyAndroid. Postindustria (IAB Tech Lab member) had proposed the same floor in our comment on #24, and our signing PR (#142) now states yours.
In our PRs, a
committhat wrote an entry keeps its key inassent[], so its result lasts as long as the record. A rejection writes no entry, so § 5.6.1 says the seller MUST keep one whoseretryisn'tsameat least untiloffer_window.end, which replacesvalid_until, or, with no end, as long as it keeps the proposal. After that date, every newcommitfails asexpired.Revised 2026-11-06: Your floor is back in our signing PR, after @pkanna000 asked for it too.
Analyzed and generated with the help of Claude, fully reviewed by me.
pkanna000 commentedon Nov 6, 2026
Implementation evidence in support of making @EvgenyAndroid's resolution normative in § 5.6.1 itself.
I read the IAB Tech Lab Agent Registry on 5 Nov 2026 (53 agents, 1,735 tool definitions, public read-only access). 52 tools across 25 agents commit or change spend: media buys, orders, campaigns. 20 of them publish an input schema, and 2 of those 20 accept anything resembling an idempotency key. Buying agents retry on timeouts automatically, so today most retried commitments have no protection beyond what § 5.6.1 will require. The reference seller agent has the same gap on
POST /proposals: IABTechLab/seller-agent#131.That argues for writing all three parts into § 5.6.1:
proposal_id.valid_untiland any hold'svalid_until(see § 5.6.2 — Holds: offered hold terms and the live hold (#66) #143), so a retry inside the offer window can't create a second commitment.The same retry problem applies to hold requests: a hold retried after a timeout can take a second hold on the same inventory. If #143 lands, the same key rule would be worth applying there, and it pairs with the per-buyer cap in #156.
KonstantinMirin commentedon Nov 6, 2026
Thanks, @pkanna000, for the registry data. Our signing PR (#142) covers your first two parts. § 4.1.2 scopes the key to one buyer and seller pair, which is wider than one
proposal_id. In § 5.6.1, reusing it with a differentCommitreturnsidempotency_conflictand writes nothing.For retention, that PR now sets @EvgenyAndroid's floor, which meets yours. A
committhe seller doesn't reject writes the buyer'scommitmententry, which carries the key, andassent[]keeps that entry for as long as the proposal exists. A rejection writes no entry, so the seller MUST keep one whoseretryisn'tsameat least untiloffer_window.end, which replaces the draft'svalid_until. In our holds PR (#143), a hold'svalid_untilcan't pass that date (§ 4.3.4), so it's already the later of your two dates.A retried hold can't take a second one. That PR says a repeated request while a hold is
requestedorheldMUST NOT start a second hold.Analyzed and generated with the help of Claude, fully reviewed by me.