From dff7cef7943adea2fef866e035f0cef65a70edfa Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Tue, 10 Sep 2024 08:53:26 -0400 Subject: [PATCH 01/10] Create 2024-09-04-FLEDGE-call-minutes.md --- meetings/2024-09-04-FLEDGE-call-minutes.md | 302 +++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 meetings/2024-09-04-FLEDGE-call-minutes.md diff --git a/meetings/2024-09-04-FLEDGE-call-minutes.md b/meetings/2024-09-04-FLEDGE-call-minutes.md new file mode 100644 index 000000000..bd2d7d666 --- /dev/null +++ b/meetings/2024-09-04-FLEDGE-call-minutes.md @@ -0,0 +1,302 @@ +# Protected Audience WICG Calls: Agenda & Notes + +Calls take place on most Wednesdays, at 11am US Eastern time; check [#88](https://github.com/WICG/turtledove/issues/88) for exceptions. + +That's 8am California = 5pm Paris time = 3pm UTC (during summer) + +This notes doc will be editable during the meeting — if you can only comment, hit reload + +Notes from past calls are all on GitHub [in this directory](https://github.com/WICG/turtledove/tree/main/meetings). + + +# Next video-call meeting: Wednesday Sept 10, 2024 + + +To be added to a Google Calendar invitation for this meeting, join the Google Group   + +If the meeting disappears from your calendar: try leaving and re-joining that group + + +## Attendees: please sign yourself in!   + +1. Michael Kleber (Google Privacy Sandbox) +2. Sven May (Google Privacy Sandbox) +3. Roni Gordon (Index Exchange) +4. Brian May (Dstillery) +5. Isaac Foster (MSFT Ads) +6. Luckey Harpley (Remerge.io) +7. Matt Davies (Bidswitch | Criteo)  +8. Arthur Coleman (IDPrivacy) +9. Courtney Johnson (Google Privacy Sandbox) +10. Orr Bernstein (Google Privacy Sandbox) +11. Matt Kendall (Index Exchange) +12. Paul Jensen (Google Privacy Sandbox) +13. Kevin Lee (Google Privacy Sandbox) +14. Fabian Höring (Criteo) +15. Harshad Mane (PubMatic) +16. Ivan Staritskii (Bidswitch | Criteo) +17. Tamara Yaeger (BidSwitch) +18. Laura Morinigo (Samsung) +19. Laurentiu Badea (OpenX) +20. Alexandre Nderagakura (Consulting | Not affiliated) +21. Bharat Rathi (Google, Privacy Sandbox) +22. Jeremy Bao (Google Privacy Sandbox) +23. Andrew Chasin (Google Privacy Sandbox) +24. Koji Ota(CyberAgent) +25. Andrew Pascoe (NextRoll) +26. David Tam (paapi.ai) +27. Suresh Chahal ( MSFT) +28. Shivani Sharma (Google Privacy Sandbox) +29. David Dabbs (Epsilon) + +## Note taker: Tamara Yaeger + +# Agenda + +## Process reminder: Join WICG + +If you want to participate in the call, please make sure you join the WICG: https\://www\.w3.org/community/wicg/ + +Contributions to this work are subject to W3C Community Contributor License Agreement (CLA) which can be found here: https\://www\.w3.org/community/about/process/cla/  + + +## Suggest agenda items here (meetings with no items may be canceled) + +- Matt Davies: + + - Quick update on the plans? + +- Fabian Höring   + +- Matt Kendall - review of deals explainer + +- + + +# Announcements + +The Microsoft Edge folks are holding every-second-Thursday meetings at this same hour to discuss their very similar "Ad Selection API" work.  See for logistics. + +Everyone is responsible for checking the accuracy of the notes doc, especially the part with their own comments - so go back later and make sure the notes are accurate.  You can even fix them on Github later!! :)  + + +# Notes  + +## Matt Davies: : Quick update on the plans? + +Michael Kleber (Google Privacy Sandbox)\ +Looking for update on .  + +Paul Jensen (Google Privacy Sandbox)\ +Centered around how BidSwitch can report on bids passed through them.  + +Matt Davies (BidSwitch)\ +Are there any further questions, any developments?\ +\ +Paul\ +Came down to adding another party to get through a port. Sounded like an automatic event would be adequate.\ +\ +Michael\ +My recollection is that there was a problem of knowing successful bid; when a particular DSP is buying in component auction run by particular component SSP. Even in that case, was BidSwitch involved in what buyer was in the auction.\ +\ +Ivan Staritskii (BidSwitch)\ +It’s not a problem for DSP to understand whether BidSwitch was in contextual bid; we need to support to send report to function executed twice. Currently SSP function for their own impression tracking, we ask them to send report to BidSwitch. Need to be able to call it 2x. We asked SSPs; not a problem to understand whether they need to send impression multiplication to BidSwitch. They have this in auction config.\ +\ +Paul\ +Proposed during contextual call theywould give list of DSPs they would like in the auction, SSP would include it in their list of buyers. Meant to convey that BidSwtich was the reason they were brought in.\ +\ +Michael\ +So SSP has responsibility when they do component auction config; identifying buyers. At the time that SSP report result is running, they know who winning buyer is, whether integrated directly or through BidSwitch (upon request of accepted buyers), at that moment in report result, the ask is for component SSP to say in addition to send report, to send “win” report to myself, also send to additional party involved in the auction. Should it be a duplicate report? Or are there some diff URLs to send to different partners?\ +\ +Matt\ +What we need is, did an impression occur, what was the spend?\ +\ +Ivan\ +We provide instruction to SSP on what they need to do in worklet to construct our impression URL. + +Paul\ +We have limits on 10 additional origins you can report to.\ +\ +Michael\ +It’s a DSP concept, but this is really an SSP? Maybe halfway in between, seems this is more about SSP choosing to send info to additional party. Maybe we should have limits? From info POV, no different than if DSP got bid on their own server, for ergonomics it would be better to go directly.\ +\ +Fabian Höring (Criteo)\ +It doesn’t need DSP support to fire the event, one idea would be to introduce a reserved event for displays, then you could register endless fenced frame reporting events for displays. + +Michael\ +Better thought of as a SSP side event, for what you’re talking about ; this ad wants to display x reporting to y collection of parties. Whereas this is focused more on structure of auction, not something knowable at time of ad construction. + +Fabian\ +Don’t agree, if SSP could handle and display FF reporting event w/out any creative data; it would be a way to provide same features calling sendReportTo multiple times + +Paul / Michael\ +It is triggered by render\ +\ +Fabian\ +If you have same event, you don’t need cooperation to send this out\ +\ +Paul\ +I think there is an auto event–\ +\ +Fabian\ +Only for clicks / redirect. There’s no auto event for displays / wins.\ +\ +Michael\ +When we added auto to deal w a few things like clicks, we did it to bring it up to level of what’s supported for render reporting.\ +\ +Matt\ +Important distinction, it would need be win + render.\ +\ +Michael\ +That’s how it works, the send report to things are only triggered by  + +Fabian\ +The SSP cannot register 2 URLs, if it could it would solve this issue.\ +\ +Michael\ +Sounds like we have same feature request to send report to additional party upon render of winning ad; only diff between Matt’s and Fabian’s proposal is about whether it’s SSP’s report result code or DSP report win code that does that invokes to send report twice, is it that correct?\ +\ +Fabian\ +If it can be handled by different FF reporting event we would have flexibility to choose whether to do it on DSP or on SSP side.\ +\ +Matt\ +Could be useful for triangulation of reporting\ +\ +Michael\ +Good for investigating discrepancies.\ +\ +Ivan\ +Just want to highlight for us it’s most important to use this for SSP more than once.\ +\ +Michael\ +To send things to multi parties POV is already something well established on the buy side of things, we don’t have equivalent on sell side, makes sense. Goal is to have either DSP or SSP or both have additional parties using upon reporting using same reporting to send back to themselves.\ +\ +Ivan\ +For us better for SSP side, the auction is to provide this ability to SSP side.\ +\ +Roni Gordon (Index Exchange)\ +Just want to better understand what happens to the SSP AV call and reporting result w respect that URL is being represented by buyer origin thru BidSwitch? We would need to know that kb time, at report results time.\ +\ +Michael\ +At RR time, the discussion we had earlier was that at RR time, the SSP logic has all info it needs to determine whether this bid came thru direct or via BidSwitch integration. Passing in as part of auction config, the SSP passing list of buyers they are integrated w directly vs w intermediary, is enough info at win time to know how to categorize it.\ +\ +Roni\ +Assumes you don’t have the same origin running through both, so you can never have both in this proposal\ +\ +Michael\ +Any particular buyer would be buying in only 1 of 2 ways, this had been worrying me from last July, assured that it was agreed was not necessary\ +\ +Roni\ +It just means you have to make a decision as an SSP. The other point, from the SSP KV call, how to know which entity is representing this buyer origin? It’s just a render URL out of thin air.  + +Michael\ +Including the buyer w the render URL in the SSP KV call seems reasonable. Would it solve this problem or others for SSPs? Should branch off the discussion.\ +\ +Paul\ +Roni is wondering about whether bid came from DSP or another party. The seller will know at score ad time\ +\ +Michael\ +Based on auction config, would only be available if SSP pushed info into their own KV server.\ +\ +Roni\ +All speaks to relationship between URL origin and buyer origin and how much overlap there is.\ +\ +Michael\ +Obvious answer is to do 2x as much work, but we won’t do it that way.\ +\ +David Tam (Paapi . ai)\ +In the auto beacon we put an impression event, what is it?\ +\ +Michael\ +It is render\ +\ +Paul\ +You can make it anything, viewability constraints, when they’re met\ +\ +David\ +How would you know in a fenced frame when those constraints are met?\ +\ +Paul\ +Like if they’ve been rendered 5 secs\ +\ +David\ +Is it on the DSP side? Can it be placed in FF?\ +\ +Paul\ +Yes\ +\ +Matt\ +Do we need to indicate in the flow that BidSwitch was involved in the KV logic? For example, we receive auction config from DSP, could we add intermediary URL and SSP would know the OpenRTB came through BidSwitch? Does that all merge together from SSP POV?\ +\ +Roni\ +We would know on the OpenRTB side that it came from BidSwitch and your provider signals are for you, but when dropped on page it’s lost because it goes back to render URLs and origins.\ +\ +Matt\ +That’s what I was worried about getting lost on page when auction config is created.\ +\ +Roni\ +It exists in auction config, but APIs don’t pass it around. It’s more about if buyer origin is shared and URLs are shared and could be uniquely identified as BidSwitch.\ +\ +Matt\ +It’s rare to have a connection via BidSwitch and also via direct. Rare if that’s the case. Any existing moments where that is the case. There could be a 3P operator like Magnite. In this instance it’s likely that it would be 2 separate signals entirely.\ +\ +Ivan\ +It’s up to SSP to decide whether to put BidSwitch in the config.\ +\ +Paul\ +Seller could put signals for score ad, could remark to buyer\ +\ +Michael\ +That means BidSwitch acting as buyer is action that is computable at every point where it’s relevant in the auction, and reportable by both DSPs and SSPs. the one gap, it’s not something automatically noble from KV server; not from info sent to trusted server. It might be possible to re-compute server side, there would probably be gaps and outstanding corrections on synchron. Aside from the Roni SSP trusted server availability question, we just need to make call to send report w multi destination domains. Well understood on DSP side, covers FF reporting events, maybe should cover send report as well. Not supported on SSP report results. Is that a good summary?\ +\ +Shivani Sharma (company?)\ +We do need to send report for diff destinations, but why do we need additional support in FF?\ +\ +Michael\ +This was the point, how do we get it triggered by render event of the frame, as opposed to later event. DSP can get it directly from existence of report send URL in report win function, but can’t be called multi times. We can extend it to allow send result to be called multi times, there would be queue for render event to happen. Or we can use the same FF mechanism and have new reserved event for render.\ +\ +Fabian\ +If I outsource creative rendering I need them to fire the event, I only care about the event. I only want to take this event for billing, I don’t care about event data inside creative, so it would be the most flexible solution.\ +\ +Shivani\ +There’s also a destination which is seller or buyer; either can register for new event type. Is the suggestion to add new destination type? It’s either seller or buyer worklet\ +\ +Fabian\ +I don’t need dest type, I register as buyer or seller and event fires off automatically\ + +## Fabian – + +To recap from last year, there is a limit of number of IGs per owner. Now it’s 2000 (10MB)  increased from 1000. What happens when same owner joins IG in same browser and quota is exceeded? + +Right now we get rid of IGs that are going to expire the soonest. Not FIFO because diff IGs can have diff expiration times. Some IGs can stick around for 3 days, some 30. This is question if we can prioritize IGs so that higher priority IGs stick around if we run into the limit? You can already use variety of mechanisms to have owner of IG choose which IGs bid if there are too many for auction.  + +My read on this is that it was discussed in April, someone was asking for it in May but has sat untouched for the last year and a quarter. Would there be utility benefit in this mechanism?\ +\ +Fabian\ +This comes up because today we have cases of ad components where we get over 10MB limit and have no feedback from Chrome on how it behaves and how to control it. It would be a useful feature to take out less important IGs from our side. It would improve performance if we can control the most important IGs.\ +\ +Michael\ +Hitting limits and having control in managing API better helps prioritize things, it’s a reasonable ask to allocate resources.\ +\ +Brian May (distillery)\ +It is common in retargeting use cases to have segments, or IGs, that have a short lifetime for things like trying to encourage someone to return to an abandoned cart; however, if they don’t respond in a couple days they probably won’t, so you’d want to free up the slot for other ads. In these cases, the short lifetime segments tend to be high value, so not having them deleted because they’re expiring soon would be important. I’m not sure priority is enough, maybe need to have a means within priority of determining how things should be expired out. More to come.\ +\ +Michael\ +Will think about how to engineer and prioritize this.\ +\ +Fabian\ +We’ll add to Github\ + +## Matt - + +Matt Kendall (Index Exchange)\ +I’ve reviewed it and go the gist, had a question about use cases for buyer reporting ID, understanding intention versus selectable buyer / seller reporting IDs.\ +\ +Paul\ +Note buyer and seller IDs existed before deals support implementation. Could be useful as conveying seat ID, but in that case there might still be use case where buyer wants to convey reporting ID only from report win, not report result.  + +Kevin Lee (Google Privacy Sandbox)\ +There is a deals developers guide coming out very soon to clear this up + +Michael\ +I will be on vacation next week. This call had no agenda items until call happened; next week we can have a call w Paul running things. Cancel a day beforehand if there are no agenda items. (Check Tuesday) From fde4556ed1162d5725c0ea59eb1cb01bc813ddc6 Mon Sep 17 00:00:00 2001 From: brusshamilton Date: Tue, 10 Sep 2024 10:45:27 -0400 Subject: [PATCH 02/10] [spec] Add basic B&A response handling (#1260) * Add basic response handling * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * address comments * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Address comments --------- Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> --- spec.bs | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 6 deletions(-) diff --git a/spec.bs b/spec.bs index 2cfca488c..893ea04ff 100644 --- a/spec.bs +++ b/spec.bs @@ -792,7 +792,7 @@ The runAdAuction(|config|) method steps are: 1. Let |auctionReportInfo| be a new [=auction report info=]. 1. If |winnerInfo| is not failure, then: 1. Set |auctionReportInfo| to the result of running [=collect forDebuggingOnly reports=] with - |bidDebugReportInfoList| and |winnerInfo|. + |bidDebugReportInfoList|, |auctionConfig|'s [=auction config/seller=], and |winnerInfo|. 1. Set |auctionReportInfo|'s [=auction report info/real time reporting contributions map=] to |realTimeContributionsMap|. 1. If |winnerInfo| is failure, then [=queue a global task=] on [=DOM manipulation task source=], @@ -2780,17 +2780,137 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report 1. Let |requestContexts| be the value of |global|'s [=associated Document's=] [=node navigable's=] [=traversable navigable's=] [=traversable navigable/saved Bidding and Auction request context=]. 1. If |requestContexts|[|requestId|] does not [=map/exist=], return null. -1. Let |response| be the result of deserializing |auctionConfig|'s [=auction config/server response=] - according to the Bidding and Auction Services IETF standard. +1. Let |requestContext| be |requestContexts|[|requestId|]. +1. Let |response| be the [=server auction response=] which is the result of + deserializing |auctionConfig|'s [=auction config/server response=] + with |requestContext| according to the Bidding and Auction Services IETF standard. Issue: TODO: Link deserialization to IETF standard when available. (WICG/turtledove#1254) -1. Construct bids based on |response|. -1. Add the bids form the |response| to |bidIgs|. +1. If |response| is failure, then return failure. +1. If |response|'s [=server auction response/is chaff=] is true, return failure. +1. If |response|'s [=server auction response/top level seller=] is not null, return failure. + + Issue: TODO: Handle Bidding and Auction Services as component auctions. + (WICG/turtledove#1254) +1. Let |winningGroup| be the [=interest group=] in the [=user agent=]'s [=interest group set=] + whose [=interest group/owner=] is |response|'s [=server auction response/interest group owner=] and + [=interest group/name=] is |response|'s [=server auction response/interest group name=]. Return failure if none found. +1. If |winningGroup|'s [=interest group/ads=] is null, then return failure. +1. Let |winningAd| be null. +1. [=list/For each=] |ad| of |winningGroup|'s [=interest group/ads=]: + 1. If |response|'s [=server auction response/ad render url=] is |ad|'s [=interest group ad/render url=], then set + |winningAd| to |ad|, and [=iteration/break=]. +1. If |winningAd| is null, then return failure. +1. Let |winningAdComponents| be a new [=list=] of [=interest group ads=]. +1. [=list/For each=] |componentAd| in |response|'s [=server auction response/ad components=]: + 1. Let |ad| be the [=interest group ad=] from |winningGroup|'s + [=interest group/ad components=] where the [=interest group ad/render url=] + equals |componentAd|. If there is no matching element, return failure. + 1. [=list/Append=] |ad| to |winningAdComponents|. +1. Let |winningBid| be a new [=generated bid=] with the following [=struct/items=]: + : [=generated bid/id=] + :: (0, 0) + : [=generated bid/for k-anon auction=] + :: TODO + : [=generated bid/bid=] + :: A new [=bid with currency=] with the following [=struct/items=]: + : [=bid with currency/value=] + :: |response|'s [=server auction response/bid=] + : [=bid with currency/currency=] + :: |response|'s [=server auction response/bid currency=] + + : [=generated bid/bid in seller currency=] + :: TODO + : [=generated bid/ad=] + :: |response|'s [=server auction response/ad render url=] + : [=generated bid/ad descriptor=] + :: |winningAd| + : [=generated bid/ad component descriptors=] + :: |winningAdComponents| + : [=generated bid/ad cost=] + :: Null + : [=generated bid/modeling signals=] + :: Null + : [=generated bid/interest group=] + :: |winningGroup| + : [=generated bid/bid ad=] + :: |winningAd| + : [=generated bid/modified bid=] + :: Null + : [=generated bid/bid duration=] + :: 0 + : [=generated bid/component seller=] + :: Null + : [=generated bid/number of mandatory ad components=] + :: [=list/Size=] of |winningAdComponents| +1. Let |buyerReportingResult| be a new [=reporting result=] with the following [=struct/items=]: + : [=reporting result/report url=] + :: The value of |response|'s [=server auction response/buyer reporting=]'s [=server auction reporting info/reporting url=]. + : [=reporting result/reporting beacon map=] + :: The value of |response|'s [=server auction response/buyer reporting=]'s [=server auction reporting info/beacon urls=]. + +1. Let |sellerReportingResult| be a new [=reporting result=] with the following [=struct/items=]: + : [=reporting result/report url=] + :: The value of |response|'s [=server auction response/top level seller reporting=]'s [=server auction reporting info/reporting url=]. + : [=reporting result/reporting beacon map=] + :: The value of |response|'s [=server auction response/top level seller reporting=]'s [=server auction reporting info/beacon urls=]. + +1. Let |componentSellerReportingResult| be a new [=reporting result=] with the following [=struct/items=]: + : [=reporting result/report url=] + :: The value of |response|'s [=server auction response/component seller reporting=]'s [=server auction reporting info/reporting url=]. + : [=reporting result/reporting beacon map=] + :: The value of |response|'s [=server auction response/component seller reporting=]'s [=server auction reporting info/beacon urls=]. + +1. Let |winningBidInfo| be a new [=leading bid info=] with the following [=struct/items=]: + : [=leading bid info/top score=] + :: |response|'s [=server auction response/score=]. + : [=leading bid info/top non-k-anon-enforced score=] + :: TODO + : [=leading bid info/top bids count=] + :: TODO + : [=leading bid info/top non-k-anon-enforced bids count=] + :: TODO + : [=leading bid info/at most one top bid owner=] + :: TODO + : [=leading bid info/leading bid=] + :: |winningBid| + : [=leading bid info/leading non-k-anon-enforced bid=] + :: TODO + : [=leading bid info/auction config=] + :: |auctionConfig| + : [=leading bid info/second highest score=] + :: TODO + : [=leading bid info/highest scoring other bids count=] + :: TODO + : [=leading bid info/highest scoring other bid=] + :: TODO + : [=leading bid info/highest scoring other bid owner=] + :: TODO + : [=leading bid info/top level seller=] + :: TODO + : [=leading bid info/top level seller signals=] + :: TODO + : [=leading bid info/component seller=] + :: TODO + : [=leading bid info/scoring data version=] + :: TODO + : [=leading bid info/buyer reporting result=] + :: |buyerReportingResult| + : [=leading bid info/seller reporting result=] + :: |sellerReportingResult| + : [=leading bid info/component seller reporting result=] + :: |componentSellerReportingResult| +1. [=list/For each=] |igPair| in |response|'s [=server auction response/bidding groups=] field: + 1. Let |ig| be the [=interest group=] in the [=user agent=]'s [=interest group set=] whose + [=interest group/owner=] is |igPair|'s [=interest group/owner=] and [=interest group/name=] is |igPair|'s + [=interest group/name=]. [=iteration/Continue=] if none found. + 1. [=list/Append=] |ig| to |bidIgs|. 1. Insert the debug reporting URLs from |response| into |bidDebugReportInfoList|. - Issue: TODO: Spec out last few steps starting from constructing bids. + Issue: TODO: Handle forDebuggingOnly reports from server auction. (WICG/turtledove#1254) +1. Return |winningBidInfo|. @@ -2929,6 +3049,56 @@ A server auction request context is a [=struct=] with the following [ (WICG/turtledove#1254) +A server auction response is a [=struct=] with the following [=struct/items=]: +
+ : is chaff + :: A [=boolean=] field indicating whether this response should be ignored. + : ad render url + :: The [=URL=] of the ad for the winning bid. + : ad components + :: A [=list=] of [=URLs=] containing the ad components for the winning bid. + : interest group name + :: The winning interest group's name as a [=string=]. + : interest group owner + :: The winning interest group's owner [=origin=]. + : bidding groups + :: A [=list=] of interest group owner and interest group name pairs that bid + in this auction. + : score + :: {{double}} or Null. TODO + : bid + :: {{double}} or Null. TODO. + : bid currency + :: [=currency tag=] or Null. TODO. + : top level seller + :: An [=origin=] or Null. Null when the server response is not feeding into an + on-device auction. Otherwise the value is the expected top-level seller for + that auction. + : ad metadata + :: A JSON [=string=]. TODO + : buyer reporting id + :: TODO. + : buyer and seller reporting id + :: TODO. + : error + :: TODO. + : buyer reporting + :: [=server auction reporting info=] + : top level seller reporting + :: [=server auction reporting info=] or Null. + : component seller reporting + :: [=server auction reporting info=] or Null. +
+ +A server auction reporting info is a [=struct=] with the following [=struct/items=]: +
+ : reporting url + :: Null or a [=URL=] + : beacon urls + :: [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] + are [=URLs=] whose [=url/schemes=] are "`https`". +
+
The getInterestGroupAdAuctionData(|config|) method steps are: From 61665eb426d00aaca0868fac948feb8aa7616d60 Mon Sep 17 00:00:00 2001 From: brusshamilton Date: Fri, 20 Sep 2024 12:38:54 -0400 Subject: [PATCH 03/10] [spec] Add component auction support for Bidding and Auction Services (#1276) * Add basic response handling * Add multiseller support * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * address comments * Don't set default valued fields with default value. Fill in some TODOs * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Address comments * s/Null:/null:/ * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Address comments * fix build * Address comments * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Some fields in both top-level and component server auctions. * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * combine server auction response bid and bid currency * formatting --------- Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> --- spec.bs | 147 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 77 insertions(+), 70 deletions(-) diff --git a/spec.bs b/spec.bs index 893ea04ff..48cce048c 100644 --- a/spec.bs +++ b/spec.bs @@ -1669,11 +1669,15 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. Let |topLevelDirectFromSellerSignalsRetrieved| be false. 1. [=list/For each=] |component| in |auctionConfig|'s [=auction config/component auctions=], [=parallel queue/enqueue steps|enqueue the following steps=] to |queue|: - 1. Let |compWinnerInfo| be the result of running [=generate and score bids=] with |component|, - |auctionConfig|, |global|, |bidIgs|, |bidDebugReportInfoList|, and |realTimeContributionsMap|. - 1. If |compWinnerInfo| is failure, return failure. + 1. If |component|'s [=auction config/server response=] is not null: + 1. Let |compWinnerInfo| be the result of running [=parse and validate server response=] with |component|, + |auctionConfig|, |global|, |bidIgs|, and |bidDebugReportInfoList|. + 1. Otherwise: + 1. Let |compWinnerInfo| be the result of running [=generate and score bids=] with |component|, + |auctionConfig|, |global|, |bidIgs|, |bidDebugReportInfoList|, and |realTimeContributionsMap|. + 1. If |compWinnerInfo| is failure, abort these steps. 1. If [=recursively wait until configuration input promises resolve=] given |auctionConfig| returns - failure, return failure. + failure, abort these steps. 1. If |topLevelDirectFromSellerSignalsRetrieved| is false: 1. Let |topLevelDirectFromSellerSignals| be the result of running [=get direct from seller signals=] given |seller|, |auctionConfig|'s @@ -2772,10 +2776,6 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report |bidDebugReportInfoList|: 1. [=Assert=] that these steps are running [=in parallel=]. -1. [=Assert=] that |topLevelAuctionConfig| is null. - - Issue: TODO: Support multi-level auctions. - (WICG/turtledove#1254) 1. Let |requestId| be the value of |auctionConfig|'s [=auction config/server response id=]. 1. Let |requestContexts| be the value of |global|'s [=associated Document's=] [=node navigable's=] [=traversable navigable's=] [=traversable navigable/saved Bidding and Auction request context=]. @@ -2789,10 +2789,11 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report (WICG/turtledove#1254) 1. If |response| is failure, then return failure. 1. If |response|'s [=server auction response/is chaff=] is true, return failure. -1. If |response|'s [=server auction response/top level seller=] is not null, return failure. - - Issue: TODO: Handle Bidding and Auction Services as component auctions. - (WICG/turtledove#1254) +1. If |response|'s [=server auction response/top level seller=] is not null: + 1. If |topLevelAuctionConfig| is null return failure. + 1. If |topLevelAuctionConfig|'s [=auction config/seller=] is not equal to + |response|'s [=server auction response/top level seller=], return failure. +1. Otherwise if |topLevelAuctionConfig| is not null, return failure. 1. Let |winningGroup| be the [=interest group=] in the [=user agent=]'s [=interest group set=] whose [=interest group/owner=] is |response|'s [=server auction response/interest group owner=] and [=interest group/name=] is |response|'s [=server auction response/interest group name=]. Return failure if none found. @@ -2802,30 +2803,30 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report 1. If |response|'s [=server auction response/ad render url=] is |ad|'s [=interest group ad/render url=], then set |winningAd| to |ad|, and [=iteration/break=]. 1. If |winningAd| is null, then return failure. -1. Let |winningAdComponents| be a new [=list=] of [=interest group ads=]. + + Issue: TODO: Check that the buyerReportingId and buyerAndSellerReportingId from the + server response match that in the |winningAd|. + (WICG/turtledove#1254) +1. Let |winningAdDescriptor| be a new [=ad descriptor=] whose [=ad descriptor/url=] is + |response|'s [=server auction response/ad render url=]. +1. Let |winningAdComponents| be a new [=list=] of [=ad descriptors=]. 1. [=list/For each=] |componentAd| in |response|'s [=server auction response/ad components=]: 1. Let |ad| be the [=interest group ad=] from |winningGroup|'s [=interest group/ad components=] where the [=interest group ad/render url=] equals |componentAd|. If there is no matching element, return failure. - 1. [=list/Append=] |ad| to |winningAdComponents|. + 1. [=list/Append=] a new [=ad descriptor=] whose [=ad descriptor/url=] is + |componentAd| to |winningAdComponents|. 1. Let |winningBid| be a new [=generated bid=] with the following [=struct/items=]: - : [=generated bid/id=] - :: (0, 0) - : [=generated bid/for k-anon auction=] - :: TODO - : [=generated bid/bid=] - :: A new [=bid with currency=] with the following [=struct/items=]: - : [=bid with currency/value=] - :: |response|'s [=server auction response/bid=] - : [=bid with currency/currency=] - :: |response|'s [=server auction response/bid currency=] - - : [=generated bid/bid in seller currency=] + : [=generated bid/id=] :: TODO + : [=generated bid/bid=] + :: |response|'s [=server auction response/bid=] + : [=generated bid/bid in seller currency=] + :: Null : [=generated bid/ad=] - :: |response|'s [=server auction response/ad render url=] + :: |response|'s [=server auction response/ad metadata=] : [=generated bid/ad descriptor=] - :: |winningAd| + :: |winningAdDescriptor| : [=generated bid/ad component descriptors=] :: |winningAdComponents| : [=generated bid/ad cost=] @@ -2837,7 +2838,7 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report : [=generated bid/bid ad=] :: |winningAd| : [=generated bid/modified bid=] - :: Null + :: Null if |topLevelAuctionConfig| is null, otherwise |response|'s [=server auction response/bid=] : [=generated bid/bid duration=] :: 0 : [=generated bid/component seller=] @@ -2861,40 +2862,35 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report :: The value of |response|'s [=server auction response/component seller reporting=]'s [=server auction reporting info/reporting url=]. : [=reporting result/reporting beacon map=] :: The value of |response|'s [=server auction response/component seller reporting=]'s [=server auction reporting info/beacon urls=]. - +1. Let |topScore| be 0.0 if |response|'s [=server auction response/score=] is null, + |response|'s [=server auction response/score=] otherwise. 1. Let |winningBidInfo| be a new [=leading bid info=] with the following [=struct/items=]: : [=leading bid info/top score=] - :: |response|'s [=server auction response/score=]. + :: |topScore| : [=leading bid info/top non-k-anon-enforced score=] - :: TODO + :: |topScore| : [=leading bid info/top bids count=] - :: TODO + :: 1 : [=leading bid info/top non-k-anon-enforced bids count=] - :: TODO - : [=leading bid info/at most one top bid owner=] - :: TODO + :: 1 : [=leading bid info/leading bid=] :: |winningBid| : [=leading bid info/leading non-k-anon-enforced bid=] - :: TODO + :: |winningBid| : [=leading bid info/auction config=] :: |auctionConfig| - : [=leading bid info/second highest score=] - :: TODO - : [=leading bid info/highest scoring other bids count=] - :: TODO : [=leading bid info/highest scoring other bid=] - :: TODO - : [=leading bid info/highest scoring other bid owner=] - :: TODO + :: Null : [=leading bid info/top level seller=] - :: TODO + :: Null if |topLevelAuctionConfig| is null, otherwise |topLevelAuctionConfig|'s [=auction config/seller=]. : [=leading bid info/top level seller signals=] - :: TODO + :: Null : [=leading bid info/component seller=] - :: TODO + :: Null if |topLevelAuctionConfig| is null, otherwise |auctionConfig|'s [=auction config/seller=]. + : [=leading bid info/bidding data version=] + :: Null : [=leading bid info/scoring data version=] - :: TODO + :: Null : [=leading bid info/buyer reporting result=] :: |buyerReportingResult| : [=leading bid info/seller reporting result=] @@ -3049,45 +3045,55 @@ A server auction request context is a [=struct=] with the following [ (WICG/turtledove#1254) -A server auction response is a [=struct=] with the following [=struct/items=]: +A server auction response is a [=struct=] that contains auction result +from an auction executed on the trusted auction server. It has the following [=struct/items=]: +
: is chaff :: A [=boolean=] field indicating whether this response should be ignored. : ad render url - :: The [=URL=] of the ad for the winning bid. + :: [=URL=]. The [=leading bid info/leading bid=]'s [=generated bid/ad descriptor=]'s [=ad descriptor/url=] from the + auction. : ad components - :: A [=list=] of [=URLs=] containing the ad components for the winning bid. + :: A [=list=] of [=URLs=]. A list of winning bid's + [=generated bid/ad component descriptors=]'s [=ad descriptor/urls=] from the + auction. : interest group name - :: The winning interest group's name as a [=string=]. + :: A [=string=]. The winning bid's interest group [=interest group/name=]. : interest group owner - :: The winning interest group's owner [=origin=]. + :: An [=origin=]. The winning bid's interest group [=interest group/owner=]. : bidding groups - :: A [=list=] of interest group owner and interest group name pairs that bid - in this auction. + :: A [=list=] of interest group [=interest group/owner=] and + interest group [=interest group/name=] pairs that bid + in the auction. : score - :: {{double}} or Null. TODO + :: Null or {{double}}. Null if the server auction is not a component auction, + otherwise the {{ScoreAdOutput/desirability}} of component auction's winning bid. : bid - :: {{double}} or Null. TODO. - : bid currency - :: [=currency tag=] or Null. TODO. + :: Null or [=bid with currency=]. Null when the server auction is not a component auction. + For component auctions, contains the winning bid's [=generated bid/modified bid=] + when not null, otherwise the winning bid's [=generated bid/bid=]. : top level seller - :: An [=origin=] or Null. Null when the server response is not feeding into an - on-device auction. Otherwise the value is the expected top-level seller for - that auction. - : ad metadata - :: A JSON [=string=]. TODO + :: Null or an [=origin=]. Null when the server auction is not a component auction. + Otherwise the value is the expected top-level seller [=origin=] for + that auction. This should match the [=auction config/seller=] for the top-level [=auction config=]. + : ad metadata + :: Null or a JSON [=string=]. Null when the server auction is not a component auction. + Otherwise the value contains the component auction's winning bid's [=generated bid/ad=]. : buyer reporting id :: TODO. : buyer and seller reporting id :: TODO. : error - :: TODO. + :: Null or [=string=]. When not null, contains an error message from the + auction executed on the trusted auction server. May be used to provide + additional context for the result of an auction. : buyer reporting - :: [=server auction reporting info=] + :: [=Server auction reporting info=] : top level seller reporting - :: [=server auction reporting info=] or Null. + :: Null or [=server auction reporting info=]. : component seller reporting - :: [=server auction reporting info=] or Null. + :: Null or [=server auction reporting info=].
A server auction reporting info is a [=struct=] with the following [=struct/items=]: @@ -7028,8 +7034,9 @@ result of [=evaluating a bidding script=], or an [=additional bid=] provided by :: A [=boolean=], initially true. If this is false, the bid is only used to determine the hypothetical winner with no k-anonymity constraints, which would be used to [=update k-anonymity counts=] only. : bid - :: A [=bid with currency=]. If the [=bid with currency/value=] is zero or negative, then this - [=interest group=] will not participate in the auction. + :: A [=bid with currency=], or null. If not null and the [=bid with currency/value=] is zero or negative, then this + [=interest group=] will not participate in the auction. This field should only + be null if the top-level auction is performed on a trusted auction server. : bid in seller currency :: A {{double}} or null. An equivalent of the original bid in seller's currency. This is either the original bid if the currency already matched, or a conversion provided by `scoreAd()`. From 3911315db55a889bf9edfcf3872c30ae7a16ba72 Mon Sep 17 00:00:00 2001 From: qingxinwu <6334674+qingxinwu@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:05:36 -0400 Subject: [PATCH 04/10] [Spec] Handle Ad-Auction-Result response header. (#1280) * Handle Ad-Auction-Result response header. * change list of hashes to a map from origin to hash * Remove adding padding. * fix a mistake in another pr. * revert a merge fix attemp. --------- Co-authored-by: Qingxin Wu --- spec.bs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/spec.bs b/spec.bs index 48cce048c..5653f5ce8 100644 --- a/spec.bs +++ b/spec.bs @@ -35,6 +35,8 @@ urlPrefix: https://github.com/WICG/turtledove/blob/main/FLEDGE_k_anonymity_serve type: dfn; text: k-anonymity; url: what-is-k-anonymity urlPrefix: https://developer.chrome.com/en/docs/privacy-sandbox/glossary/ type: dfn; text: ad creative; url: ad-creative +spec: RFC4648; urlPrefix: https://datatracker.ietf.org/doc/html/rfc4648 + type: dfn; text: base64url; url: section-5 spec: RFC6234; urlPrefix: https://www.ietf.org/rfc/rfc6234.txt type: dfn; text: SHA-256 urlPrefix: https://datatracker.ietf.org/doc/html/rfc8032 @@ -2773,9 +2775,15 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=] To parse and validate server response given an [=auction config=] |auctionConfig|, an [=auction config=]-or-null |topLevelAuctionConfig|, a [=global object=] |global|, a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug reporting info=] -|bidDebugReportInfoList|: +|bidDebugReportInfoList|, perform the following steps. They return a [=leading bid info=] or a failure. 1. [=Assert=] that these steps are running [=in parallel=]. +1. Let |hash| be the [=SHA-256=] of |auctionConfig|'s [=auction config/server response=]. +1. Let |capturedAuctionHeaders| be |global|'s [=associated Document's=] [=node navigable's=] + [=traversable navigable's=] [=traversable navigable/captured ad auction result headers=]. +1. Let |seller| be |auctionConfig|'s [=auction config/seller=]. +1. If |capturedAuctionHeaders|[|seller|] does not [=map/exist=] or does not [=list/contain=] |hash|, + then return failure. 1. Let |requestId| be the value of |auctionConfig|'s [=auction config/server response id=]. 1. Let |requestContexts| be the value of |global|'s [=associated Document's=] [=node navigable's=] [=traversable navigable's=] [=traversable navigable/saved Bidding and Auction request context=]. @@ -5576,9 +5584,6 @@ prevents a leak of the user's ad interest group membership to the server. # Fetch Patch for Auction Headers # {#fetch-patch-for-auction-headers} - Issue: TODO: Handle Bidding and Auction Server header. - (WICG/turtledove#1254) - This section specifies a manner by which some data, including [=additional bids=] and [=direct from seller signals=], may be provided to auctions such that the data is only used within their intended auction. @@ -5586,7 +5591,8 @@ their intended auction. Any {{Document}} in a [=traversable navigable=] may run a Protected Audience auction (with {{Window/navigator}}.{{Navigator/runAdAuction()}}) whose [=script runners=] functions receive signal objects derived from JSON from an [:Ad-Auction-Signals:] header, or [=additional bids=] derived from -an [:Ad-Auction-Additional-Bid:] header, captured by a {{WindowOrWorkerGlobalScope/fetch()}} call +an [:Ad-Auction-Additional-Bid:] header, or response blob's [=base64url=] encoded [=SHA-256=] hash +derived from an [:Ad-Auction-Result:] header, captured by a {{WindowOrWorkerGlobalScope/fetch()}} call (using the {{RequestInit/adAuctionHeaders}} option) initiated by any *other* {{Document}} in the *same* [=traversable navigable=], or from an iframe navigation @@ -5624,6 +5630,10 @@ the [=string representation=] of a [=version 4 UUID=] and whose [=map/values=] are [=server auction request contexts=].
+Each [=traversable navigable=] has a captured ad auction result +headers, which is a [=map=] whose [=map/keys=] are [=origins=] and [=map/values=] are +[=strings=]. +
Modify the definition of a [=request=]: @@ -5718,6 +5728,24 @@ corresponds to a single [=additional bid=]. The response may include more than o by specifying multiple instances of the [:Ad-Auction-Additional-Bid:] response header.
+

The \`Ad-Auction-Result\` +HTTP response header.

+ +The \`Ad-Auction-Result\` response header provides the +[=base64url=] encoded [=SHA-256=] hash of the response blob. Multiple hashes can be included in a +response by either repeating the header or by specifying multiple hashes separated by a "`,`" character. + +
+
+    Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=,9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
+  
+ is equivalent to +
+    Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=
+    Ad-Auction-Result: 9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
+  
+
+
The following steps will be added to the [=HTTP fetch=] algorithm, immediately under the step "If internalResponse’s [=status=] is a [=redirect status=]:" @@ -5740,7 +5768,8 @@ The following step will be added to the [=HTTP fetch=] algorithm, before step [=node navigable=]'s [=traversable navigable=]. 1. Run [=update captured headers=] with |navigable|'s [=traversable navigable/captured ad auction signals headers=], |navigable|'s - [=traversable navigable/captured ad auction additional bids headers=], |response|'s + [=traversable navigable/captured ad auction additional bids headers=], |navigable|'s + [=traversable navigable/captured ad auction result headers=], |response|'s [=response/header list=], and |request|'s [=request/URL=]'s [=url/origin=].
@@ -5751,6 +5780,7 @@ The following algorithm will be added to the [[FETCH#fetching]] section: To update captured headers with a [=traversable navigable/captured ad auction signals headers=] |storedSignalsHeaders|, [=traversable navigable/captured ad auction additional bids headers=] |storedAdditionalBidsHeaders|, + [=traversable navigable/captured ad auction result headers=] |storedAuctionResultHeaders|, [=header list=] |responseHeaders|, and [=origin=] |requestOrigin|: 1. Let |adAuctionSignals| be the result of [=header list/getting=] [:Ad-Auction-Signals:] from |responseHeaders|. @@ -5762,6 +5792,7 @@ The following algorithm will be added to the [[FETCH#fetching]] section: the header value. 1. [=Handle ad auction signals header value=] given |adAuctionSignals|, |storedSignalsHeaders| and |requestOrigin|. + 1. Let |additionalBids| be the result of [=header list/getting, decoding, and splitting=] [:Ad-Auction-Additional-Bid:] from |responseHeaders|. 1. If |additionalBids| is not null: @@ -5777,6 +5808,20 @@ The following algorithm will be added to the [[FETCH#fetching]] section: 1. If |nonce|'s [=string/length=] is not 36, then [=iteration/continue=]. 1. Set |storedAdditionalBidsHeaders|[|nonce|] to |nonceAndAdditionalBid|[1]. + 1. Let |adAuctionResults| be the result of [=header list/getting, decoding, and splitting=] + [:Ad-Auction-Result:] from |responseHeaders|. + 1. If |adAuctionResults| is not null, [=list/for each=] |result| of |adAuctionResults|: + 1. [=Strip leading and trailing ASCII whitespace=] from |result|. + 1. If |result| is "", or contains [=code points=] U+002B (`+`) or U+002F (`/`), then + [=iteration/continue=]. + 1. Replace every U+2212 (`-`) [=code point=] in |result| with U+002B (`+`). + 1. Replace every U+005F(`_`) [=code point=] in |result| with U+002F (`/`). + 1. Let |hash| be the result of running [=forgiving-base64 decode=] with |result|. + 1. If |hash| is not failure, and |hash|'s [=string/length=] is 32: + 1. If |storedAuctionResultHeaders|[|requestOrigin|] [=map/exists=], then [=list/append=] |hash| + to |storedAuctionResultHeaders|. + 1. Otherwise, [=map/set=] |storedAuctionResultHeaders|[|requestOrigin|] to « |hash| ». +
From 85008430922987630422a60926ab33530010a4e0 Mon Sep 17 00:00:00 2001 From: qingxinwu <6334674+qingxinwu@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:00:41 -0400 Subject: [PATCH 05/10] [Spec] Handle reporting id from B&A server response (#1281) * in-progress * almost done, with one question. * finish * clearer document --------- Co-authored-by: Qingxin Wu --- spec.bs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/spec.bs b/spec.bs index 5653f5ce8..fd5693c51 100644 --- a/spec.bs +++ b/spec.bs @@ -2808,13 +2808,14 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report 1. If |winningGroup|'s [=interest group/ads=] is null, then return failure. 1. Let |winningAd| be null. 1. [=list/For each=] |ad| of |winningGroup|'s [=interest group/ads=]: - 1. If |response|'s [=server auction response/ad render url=] is |ad|'s [=interest group ad/render url=], then set - |winningAd| to |ad|, and [=iteration/break=]. -1. If |winningAd| is null, then return failure. - - Issue: TODO: Check that the buyerReportingId and buyerAndSellerReportingId from the - server response match that in the |winningAd|. - (WICG/turtledove#1254) + 1. If |response|'s [=server auction response/ad render url=] is |ad|'s + [=interest group ad/render url=], then set |winningAd| to |ad|, and [=iteration/break=]. +1. Return failure if any of the following conditions hold: + * |winningAd| is null; + * |response|'s [=server auction response/buyer and seller reporting id=] is not null and not + |winningAd|'s [=interest group ad/buyer and seller reporting ID=]; + * |response|'s [=server auction response/buyer reporting id=] is not null and not + |winningAd|'s [=interest group ad/buyer reporting ID=]. 1. Let |winningAdDescriptor| be a new [=ad descriptor=] whose [=ad descriptor/url=] is |response|'s [=server auction response/ad render url=]. 1. Let |winningAdComponents| be a new [=list=] of [=ad descriptors=]. @@ -3088,10 +3089,12 @@ from an auction executed on the trusted auction server. It has the following [=s : ad metadata :: Null or a JSON [=string=]. Null when the server auction is not a component auction. Otherwise the value contains the component auction's winning bid's [=generated bid/ad=]. - : buyer reporting id - :: TODO. - : buyer and seller reporting id - :: TODO. + : buyer reporting id + :: Null or a [=string=]. When not null, this will be verified with the winning bid's + [=generated bid/ad=]'s [=interest group ad/buyer reporting ID=]. + : buyer and seller reporting id + :: Null or a [=string=]. When not null, this will be verified with the winning bid's + [=generated bid/ad=]'s [=interest group ad/buyer and seller reporting ID=]. : error :: Null or [=string=]. When not null, contains an error message from the auction executed on the trusted auction server. May be used to provide From 9a4a2701d76dcf2da547a827a3d8a6cf1ebc7f73 Mon Sep 17 00:00:00 2001 From: brusshamilton Date: Mon, 23 Sep 2024 15:06:52 -0400 Subject: [PATCH 06/10] [spec] Fix semantics around Abort Signal for runAdAuction() (#1266) * Fix semantics around Abort Signal for runAdAuction() * Address comments * Address more comments * Address comments * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> --------- Co-authored-by: Paul Jensen Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> --- spec.bs | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/spec.bs b/spec.bs index fd5693c51..5f5e6c531 100644 --- a/spec.bs +++ b/spec.bs @@ -774,11 +774,11 @@ The runAdAuction(|config|) method steps are: 1. Let |signal| be |config|["{{AuctionAdConfig/signal}}"]. 1. If |signal| is [=AbortSignal/aborted=], then [=reject=] |p| with |signal|'s [=AbortSignal/abort reason=] and return |p|. - 1. [=AbortSignal/Add|Add the following abort steps=] to |signal|: - 1. [=Reject=] |p| with |signal|’s [=AbortSignal/abort reason=]. - 1. Run [=update bid counts=] with |bidIgs|. - 1. Run [=interest group update=] with |auctionConfig|'s [=auction config/interest group buyers=] - and |settings|'s [=environment settings object/policy container=]. + 1. Otherwise [=AbortSignal/Add|add the following abort steps=] to |signal|: + 1. Set |auctionConfig|'s [=auction config/aborted=] to true. + 1. Set |auctionConfig|'s [=auction config/abort reason=] to |signal|'s [=AbortSignal/abort reason=]. + 1. [=list/For each=] |auction| in |auctionConfig|'s [=auction config/component auctions=]: + 1. Set |auction|'s [=auction config/aborted=] to true. 1. [=Assert=] that |settings|'s [=environment settings object/origin=] is not an [=opaque origin=] and its [=origin/scheme=] is "`https`". 1. Let |queue| be the result of [=starting a new parallel queue=]. @@ -797,7 +797,10 @@ The runAdAuction(|config|) method steps are: |bidDebugReportInfoList|, |auctionConfig|'s [=auction config/seller=], and |winnerInfo|. 1. Set |auctionReportInfo|'s [=auction report info/real time reporting contributions map=] to |realTimeContributionsMap|. - 1. If |winnerInfo| is failure, then [=queue a global task=] on [=DOM manipulation task source=], + 1. If |auctionConfig|'s [=auction config/aborted=] is true: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |global|, to + [=reject=] |p| with |auctionConfig|'s [=auction config/abort reason=]. + 1. Otherwise if |winnerInfo| is failure, then [=queue a global task=] on [=DOM manipulation task source=], given |global|, to [=reject=] |p| with a "{{TypeError}}". 1. Otherwise if |winnerInfo| is null or |winnerInfo|'s [=leading bid info/leading bid=] is null: 1. [=Queue a global task=] on [=DOM manipulation task source=], given |global|, to [=resolve=] @@ -818,10 +821,10 @@ The runAdAuction(|config|) method steps are: 1. If |auctionConfig|'s [=auction config/resolve to config=] is false, then set |result| to |urn|. 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |global|, to resolve |p| with |result|. + 1. Run [=update previous wins=] with |winner|. 1. Run [=interest group update=] with |auctionConfig|'s [=auction config/interest group buyers=] and |settings|'s [=environment settings object/policy container=]. 1. Run [=update bid counts=] with |bidIgs|. - 1. Run [=update previous wins=] with |winner|. 1. Return |p|.
@@ -1659,6 +1662,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: batcher=] with |auctionConfig|'s [=auction config/max trusted scoring signals url length=]. 1. Let « |bidGenerators|, |negativeTargetInfo| » be the result of running [=build bid generators map=] with |auctionConfig|. +1. If |auctionConfig|'s [=auction config/aborted=] is true, return failure. 1. Let |leadingBidInfo| be a new [=leading bid info=]. 1. Let |queue| be the result of [=starting a new parallel queue=]. 1. Let |capturedAuctionHeaders| be |global|'s [=associated Document's=] [=node navigable's=] @@ -1699,6 +1703,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: and |realTimeContributionsMap|. 1. Decrement |pendingComponentAuctions| by 1. 1. Wait until |pendingComponentAuctions| is 0. + 1. If |auctionConfig|'s [=auction config/aborted=] is true, return failure. 1. If |leadingBidInfo|'s [=leading bid info/leading bid=] is null, return null. 1. Let |winningComponentConfig| be |leadingBidInfo|'s [=leading bid info/auction config=]. 1. Set |leadingBidInfo|'s [=leading bid info/auction config=] to |auctionConfig|. @@ -1943,6 +1948,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: |componentAuctionExpectedCurrency|, |topLevelOrigin|, and |realTimeContributionsMap|. 1. Decrement |pendingBuyers| by 1. 1. Wait until both |pendingBuyers| and |pendingAdditionalBids| are 0. +1. If |auctionConfig|'s [=auction config/aborted=] is true, return failure. 1. If |leadingBidInfo|'s [=leading bid info/leading bid=] is null, return null. 1. If |topLevelAuctionConfig| is null: 1. Let « |sellerSignals|, |reportResultBrowserSignals| » be the result of running @@ -4083,6 +4089,7 @@ from querying the server during an auction.
To update k-anonymity cache for key given a [=SHA-256=] |hashCode|: + 1. [=Assert=] that these steps are running [=in parallel=]. 1. Let |record| be a new [=k-anonymity record=]. 1. Set |record|'s [=k-anonymity record/timestamp=] field to the [=current wall time=]. 1. Set |record|'s [=k-anonymity record/is k-anonymous=] field to the result of executing [=query k-anonymity count=] for |hashCode|. @@ -4091,6 +4098,7 @@ from querying the server during an auction.
To update k-anonymity cache for interest group given an [=interest group=] |ig|: + 1. [=Assert=] that these steps are running [=in parallel=]. 1. [=list/For each=] |igAd| of |ig|'s [=interest group/ads=]: 1. Compute the |adHashCode| following [=compute the key hash of ad=] for |ig| and |igAd|. 1. Run [=update k-anonymity cache for key=] on |adHashCode|. @@ -6463,13 +6471,19 @@ An auction config is a [=struct=] with the following [=struct/items=] encrypted response stored in [=auction config=]'s [=auction config/server response=] field. Must be null when [=auction config=]'s [=auction config/server response=] is null, and non-null otherwise. + : aborted + :: A [=boolean=] indicating whether the auction has been aborted, initially false. + : abort reason + :: {{any}}.
To wait until configuration input promises resolve given an [=auction config=] |auctionConfig|: - 1. Wait until |auctionConfig|'s [=auction config/pending promise count=] is 0. + 1. Wait until either |auctionConfig|'s [=auction config/pending promise count=] is 0 + or |auctionConfig|'s [=auction config/aborted=] is true. + 1. If |auctionConfig|'s [=auction config/aborted=] is true, return failure. 1. [=Assert=] |auctionConfig|'s [=auction config/auction signals=], [=auction config/seller signals=], [=auction config/per buyer signals=], [=auction config/per buyer currencies=], [=auction config/per buyer timeouts=], [=auction config/per buyer cumulative timeouts=], From d21ed7f01a1fb7fe9675c73d1f08ebb5e4cf8346 Mon Sep 17 00:00:00 2001 From: brusshamilton Date: Tue, 24 Sep 2024 11:40:05 -0400 Subject: [PATCH 07/10] [spec] Remove redundant 'is chaff' field (#1282) --- spec.bs | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec.bs b/spec.bs index 5f5e6c531..649d35161 100644 --- a/spec.bs +++ b/spec.bs @@ -2802,7 +2802,6 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report Issue: TODO: Link deserialization to IETF standard when available. (WICG/turtledove#1254) 1. If |response| is failure, then return failure. -1. If |response|'s [=server auction response/is chaff=] is true, return failure. 1. If |response|'s [=server auction response/top level seller=] is not null: 1. If |topLevelAuctionConfig| is null return failure. 1. If |topLevelAuctionConfig|'s [=auction config/seller=] is not equal to @@ -3064,8 +3063,6 @@ A server auction response is a [=struct=] that contains auction resul from an auction executed on the trusted auction server. It has the following [=struct/items=]:
- : is chaff - :: A [=boolean=] field indicating whether this response should be ignored. : ad render url :: [=URL=]. The [=leading bid info/leading bid=]'s [=generated bid/ad descriptor=]'s [=ad descriptor/url=] from the auction. From 394ef7f0c6f5d3a5644d5e0c6c3257b4ad85f797 Mon Sep 17 00:00:00 2001 From: David Tam Date: Thu, 26 Sep 2024 22:39:07 +0100 Subject: [PATCH 08/10] Update fledge-tester-list.md (#1287) Added Paapi as a DSP --- fledge-tester-list.md | 1 + 1 file changed, 1 insertion(+) diff --git a/fledge-tester-list.md b/fledge-tester-list.md index 8ffad7853..aba388d25 100644 --- a/fledge-tester-list.md +++ b/fledge-tester-list.md @@ -88,6 +88,7 @@ The usefulness of this page depends on testers sharing information and updates. | Lucead | DSP & SSP | Testing in progress | | privacysandbox@lucead.com | | Optable | DSP & SSP | Testing in progress | | privacysandbox@optable.co | | Taboola | DSP & SSP | Testing in progress | | privacy-sandbox@taboola.com | +| Paapi | DSP | Testing in progress | | privacysandbox@paapi.ai | ## Table - Publishers and Advertisers Interested in Testing or Early Adoption Companies who may be interested in participating in tests and early adoption opportunities provided by ad tech companies. From 25ee9fd45ae71a14788437fda9972123aaf25826 Mon Sep 17 00:00:00 2001 From: "Benjamin \"Russ\" Hamilton" Date: Mon, 30 Sep 2024 11:00:07 -0400 Subject: [PATCH 09/10] [spec] Add Bidding and auction payload customization support (#1274) * Add payload optimization * Add missing = * Add constraint on request size * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Address comments * Address comments * Add domintro for AdAuctionDataConfig * Fix missing description * Apply suggestions from code review Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> * Describe values of {{AdAuctionDataConfig/perBuyerConfig}} * Fix filtering logic --------- Co-authored-by: qingxinwu <6334674+qingxinwu@users.noreply.github.com> --- spec.bs | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 4 deletions(-) diff --git a/spec.bs b/spec.bs index 649d35161..20832711c 100644 --- a/spec.bs +++ b/spec.bs @@ -2992,17 +2992,53 @@ partial interface Navigator { Promise getInterestGroupAdAuctionData(AdAuctionDataConfig config); }; +dictionary AdAuctionData { + required Uint8Array request; + required USVString requestId; +}; + + + dictionary AdAuctionDataConfig { required USVString seller; required USVString coordinatorOrigin; + unsigned long requestSize; + record<USVString, AdAuctionDataBuyerConfig> perBuyerConfig; }; + -dictionary AdAuctionData { - required Uint8Array request; - required USVString requestId; +
+
{{AdAuctionDataConfig/seller}} +
The seller that will be used as the {{AuctionAdConfig/seller}} in the + following {{AuctionAdConfig}} passed to {{Window/navigator}}.{{Navigator/runAdAuction()}}. +
{{AdAuctionDataConfig/coordinatorOrigin}} +
The origin of the coordinator hosting public encryption keys for the server + running the ad auction. The [=origin/scheme=] must be "`https`". An implementation + may select which coordinators are acceptable. +
{{AdAuctionDataConfig/requestSize}} +
The desired size for the returned {{AdAuctionData/request}}. If any buyers are specified in + {{AdAuctionDataConfig/perBuyerConfig}}, this will be the exact size of the returned {{AdAuctionData/request}}. + Otherwise the returned {{AdAuctionData/request}}'s size will be at most the + {{AdAuctionDataConfig/requestSize}}. +
{{AdAuctionDataConfig/perBuyerConfig}} +
[=map/Keys=] are [=serialization of an origin|serialized origins=] of + buyers that should be included in the returned request. [=map/Values=] are + {{AdAuctionDataBuyerConfig}} for that buyer. +
+ + +dictionary AdAuctionDataBuyerConfig { + unsigned long targetSize; }; +
+
{{AdAuctionDataBuyerConfig/targetSize}} +
The size of the request to allocate for this buyer. Required when + {{AdAuctionDataConfig}}'s {{AdAuctionDataConfig/requestSize}} is not + specified. +
+ A server auction interest group is a [=struct=] with the following [=struct/items=]:
: name @@ -3019,6 +3055,9 @@ A server auction interest group is a [=struct=] with the following [= from the [=interest group/ad components=] field. : browser signals :: A [=server auction browser signals=]. + : priority + :: A {{double}}. Used to select which interest groups for a given buyer are excluded + from the serialized request due to space limitations.
A server auction browser signals is a [=struct=] with the following [=struct/items=]: @@ -3121,11 +3160,12 @@ A server auction reporting info is a [=struct=] with the following [=
-The getInterestGroupAdAuctionData(|config|) method steps are: +The getInterestGroupAdAuctionData(|configIDL|) method steps are: 1. Let |global| be [=this=]'s [=relevant global object=]. 1. If |global|'s [=associated Document=] is not [=allowed to use=] the "[=run-ad-auction=]" [=policy-controlled feature=], then [=exception/throw=] a "{{NotAllowedError}}" {{DOMException}}. +1. Let |config| be the result of running [=parse and verify ad auction data config=] on |configIDL|. 1. Let |p| be [=a new promise=]. 1. Let |queue| be the result of [=starting a new parallel queue=]. 1. [=parallel queue/enqueue steps|Enqueue the following steps=] to |queue|: @@ -3134,6 +3174,9 @@ The getInterestGroupAdAuctionData(|config|) meth 1. [=list/For each=] |ig| of the [=user agent=]'s [=interest group set=]: 1. If |ig|'s [=interest group/ads=] is null or [=list/is empty=], [=iteration/continue=]. 1. Let |owner| be |ig|'s [=interest group/owner=]. + 1. If |config|'s [=auction data config/per buyer config=] [=map/is not empty=] and + |config|'s [=auction data config/per buyer config=][|owner|] does not + [=map/exist=], then [=iteration/continue=]. 1. If |igMap|[|owner|] does not [=map/exist=], then [=map/set=] |igMap|[|owner|] to a new [=list=]. 1. Let |ads| be a new [=list=]. 1. [=list/For each=] |ad| in |ig|'s [=interest group/ads=], [=list/append=] |ad|'s [=interest group ad/ad render ID=] to |ads|. @@ -3173,6 +3216,8 @@ The getInterestGroupAdAuctionData(|config|) meth :: |components| : [=server auction interest group/browser signals=] :: |browserSignals| + : [=server auction interest group/priority=] + :: |ig|'s [=interest group/priority=] 1. [=list/Append=] |serverIg| to |igMap|[|owner|]. 1. Let |result| be a new {{AdAuctionData}}. 1. Let |requestId| be the [=string representation=] of a [=version 4 UUID=]. @@ -3193,6 +3238,51 @@ The getInterestGroupAdAuctionData(|config|) meth
+
+ To parse and verify ad auction data config given an {{AdAuctionDataConfig}} |configIDL|: + + 1. Let |seller| be the result of running [=parse an https origin=] on + |configIDL|["{{AdAuctionDataConfig/seller}}"]. + 1. Let |coordinator| be the result of running [=parse an https origin=] on + |configIDL|["{{AdAuctionDataConfig/coordinatorOrigin}}"]. + 1. If |seller| or |coordinator| are failure, then [=exception/throw=] a {{TypeError}}. + 1. Let |config| be a new [=auction data config=] with the following [=struct/items=]: + : [=auction data config/seller=] + :: |seller| + : [=auction data config/coordinator=] + :: |coordinator| + : [=auction data config/request size=] + :: |configIDL|["{{AdAuctionDataConfig/requestSize}}"] if it [=map/exists=], null otherwise + : [=auction data config/per buyer config=] + :: The result of running [=parse per buyer auction data configs=] on + |configIDL|["{{AdAuctionDataConfig/perBuyerConfig}}"] + 1. If |config|'s [=auction data config/per buyer config=] [=map/is not empty=] + and |config|'s [=auction data config/request size=] is null: + 1. Let |requestSize| be 0. + 1. [=list/For each=] |buyerConfig| of |config|'s [=auction data config/per buyer config=]'s [=map/values=]: + 1. If |buyerConfig|'s [=auction data buyer config/size=] is null, + then [=exception/throw=] a {{TypeError}}. + 1. Set |requestSize| to |requestSize| + |buyerConfig|'s [=auction data buyer config/size=]. + 1. Set |config|'s [=auction data config/request size=] to |requestSize|. + 1. Return |config|. +
+ +
+ To parse per buyer auction data configs given an + {{AdAuctionDataBuyerConfig}} |perBuyerConfigIDL|: + 1. Let |configs| be a new [=ordered map=] whose [=map/keys=] are [=origins=] + and whose [=map/values=] are [=auction data configs=]. + 1. [=map/For each=] |buyerIDL| → |buyerConfigIDL| of |perBuyerConfigIDL|: + 1. Let |buyerConfig| be a new [=auction data buyer config=]. + 1. Set |buyerConfig|'s [=auction data buyer config/size=] to + |buyerConfigIDL|["{{AdAuctionDataBuyerConfig/targetSize}}"] if it + [=map/exists=], null otherwise. + 1. Let |buyer| be the result of running [=parse an https origin=] on |buyerIDL|. + 1. If |buyer| is failure, then [=exception/throw=] a {{TypeError}}. + 1. [=map/Set=] |configs|[|buyer|] to |buyerConfig|. + 1. Return |configs|. +
+ # Reporting # {#reporting} ## {{InterestGroupBiddingAndScoringScriptRunnerGlobalScope/forDebuggingOnly}} ## {#for-debugging-only-header} @@ -7520,6 +7610,31 @@ for a given [=k-anonymity key=]. These records are stored in the [=user agent=]. :: The [=moment=] when the k-anonymity status in this record was last fetched.
+

auction data config

+ +An auction data config is a [=struct=] with the following [=struct/items=]: + +
+ : seller + :: An [=origin=]. + The origin of the seller running the ad auction. The [=origin/scheme=] must be "`https`". + : coordinator + :: The origin of the coordinator hosting public encryption keys for the server + running the ad auction. The [=origin/scheme=] must be "`https`". + : request size + :: {{unsigned long}} or null. An optional field, containing the desired size + for the returned encrypted request blob. + : per buyer config + :: A [=map=] whose [=map/keys=] are [=origins=] and [=map/values=] are [=auction data buyer config=]. +
+ +An auction data buyer config is a [=struct=] with the following [=struct/items=]: +
+ : size + :: {{unsigned long}} or null. An optional field, initially null, containing the + size of the request to allocate to this buyer. +
+ # Privacy Considerations # {#privacy-considerations} Protected Audience aims to advance the privacy of remarketing and custom audience From f112a2a285c203c82fe366a2920bfa43769fed4b Mon Sep 17 00:00:00 2001 From: qingxinwu <6334674+qingxinwu@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:01:39 -0400 Subject: [PATCH 10/10] [Spec] Handle B&A server response promise (#1285) * in progress with question * almost finished. * address comments * address comments * address comments, and fix a possible bug * address comment. * address comment --------- Co-authored-by: Qingxin Wu --- spec.bs | 78 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/spec.bs b/spec.bs index 20832711c..c419417ff 100644 --- a/spec.bs +++ b/spec.bs @@ -1146,10 +1146,36 @@ To validate and convert auction ad config given an {{AuctionAdConfig} 1. If |seller| is failure, then return failure. 1. Set |auctionConfig|'s [=auction config/seller=] to |seller|. 1. If |config|["{{AuctionAdConfig/serverResponse}}"] [=map/exists=]: - 1. If |config|["{{AuctionAdConfig/requestId}}"] does not [=map/exist=], then [=exception/throw=] - a {{TypeError}}. - 1. Set |auctionConfig|'s [=auction config/server response=] to |config|["{{AuctionAdConfig/serverResponse}}"]. - 1. Set |auctionConfig|'s [=auction config/server response id=] to |config|["{{AuctionAdConfig/requestId}}"]. + 1. If |config|["{{AuctionAdConfig/requestId}}"] does not [=map/exist=], then [=exception/throw=] a + {{TypeError}}. + 1. Let |resolvedAndTypeChecked| be the promise representing performing the following steps + [=upon fulfillment=] of |config|["{{AuctionAdConfig/serverResponse}}"] with |result|: + 1. Set |auctionConfig|'s [=auction config/server response=] to the [=ArrayBuffer/transferred=] + |result|. + 1. Set |auctionConfig|'s [=auction config/server response id=] to + |config|["{{AuctionAdConfig/requestId}}"]. + 1. [=Upon rejection=] of |resolvedAndTypeChecked|: + 1. Set |auctionConfig|'s [=auction config/server response=] to failure. + + Note: The JavaScript code calling {{Navigator/runAdAuction()}} is responsible for *not* + resolving |config|["{{AuctionAdConfig/serverResponse}}"] until server responses have been + retrieved from one or more [:Ad-Auction-Result:] headers, as resolving this Promise early + would cause a race condition in which the [=script runners=] might run without the server + responses that it needs. There are two ways that server responses can be retrieved.
+ (1) The JavaScript code issues a [=request=] whose [=request/initiator type=] + is `"fetch"` and whose {{RequestInit/adAuctionHeaders}} option is set to `true`. The + JavaScript code has to resolve |config|["{{AuctionAdConfig/serverResponse}}"] after the + corresponding call to {{WindowOrWorkerGlobalScope/fetch()}} has resolved to a [=response=]. + The JavaScript code can also choose to wait to call {{Navigator/runAdAuction()}} until after + the corresponding call to {{WindowOrWorkerGlobalScope/fetch()}} has resolved to a [=response=], + and can then immediately resolve |config|["{{AuctionAdConfig/serverResponse}}"];
+ (2) issue an iframe navigation + request with the <{iframe/adauctionheaders}> content attribute set to `true`. + In this case, the JavaScript code is retrieved as part of the iframe navigation response, + at which point the JavaScript code in the iframe makes the call to + {{Navigator/runAdAuction()}}, and |config|["{{AuctionAdConfig/serverResponse}}"] can be + specified directly without a Promise. + 1. Otherwise: 1. If |config|["{{AuctionAdConfig/requestId}}"] [=map/exists=], then [=exception/throw=] a {{TypeError}}. @@ -1229,17 +1255,15 @@ To validate and convert auction ad config given an {{AuctionAdConfig} resolving |config|["{{AuctionAdConfig/additionalBids}}"] until additional bids have been retrieved from one or more [:Ad-Auction-Additional-Bid:] headers, as resolving this Promise early would cause a race condition in which additional bids might not be included in the - auction. There are two ways that additional bids can be retrieved. The first is for the - JavaScript code to issue a [=request=] whose [=request/initiator type=] is `"fetch"` and whose + auction. There are two ways that additional bids can be retrieved.
+ (1) The JavaScript code issues a [=request=] whose [=request/initiator type=] is `"fetch"` and whose {{RequestInit/adAuctionHeaders}} option is set to `true`. The JavaScript code has to resolve |config|["{{AuctionAdConfig/additionalBids}}"] after the corresponding call to {{WindowOrWorkerGlobalScope/fetch()}} has resolved to a [=response=]. The JavaScript code can also choose to wait to call {{Navigator/runAdAuction()}} until after the corresponding call to {{WindowOrWorkerGlobalScope/fetch()}} has resolved to a response, - and can then immediately resolve |config|["{{AuctionAdConfig/additionalBids}}"]. - - The second way that additional bids can be retrieved is by issuing an - iframe navigation + and can then immediately resolve |config|["{{AuctionAdConfig/additionalBids}}"];
+ (2) issue an iframe navigation request with the <{iframe/adauctionheaders}> content attribute set to `true`. In this case, the JavaScript code is retrieved as part of the iframe navigation response, at which point the JavaScript code in the iframe makes the call to @@ -1259,22 +1283,21 @@ To validate and convert auction ad config given an {{AuctionAdConfig} until direct from seller signals have been retrieved from one or more [:Ad-Auction-Signals:] headers, as resolving this Promise early would cause a race condition in which the [=script runners=] might run without the direct from seller signals that it needs. There are two ways that - direct from seller signals can be retrieved. The first is for the JavaScript code to issue a - [=request=] whose [=request/initiator type=] is `"fetch"` and whose + direct from seller signals can be retrieved.
+ (1) The JavaScript code issues a [=request=] whose [=request/initiator type=] is `"fetch"` and whose {{RequestInit/adAuctionHeaders}} option is set to `true`. The JavaScript code has to resolve |config|["{{AuctionAdConfig/directFromSellerSignalsHeaderAdSlot}}"] after the corresponding call to {{WindowOrWorkerGlobalScope/fetch()}} has resolved to a [=response=]. The JavaScript code can also choose to wait to call {{Navigator/runAdAuction()}} until after the corresponding call to {{WindowOrWorkerGlobalScope/fetch()}} has resolved to a [=response=], and can then immediately resolve - |config|["{{AuctionAdConfig/directFromSellerSignalsHeaderAdSlot}}"]. The second way that - direct from seller signals can be retrieved is by issuing an - iframe navigation + |config|["{{AuctionAdConfig/directFromSellerSignalsHeaderAdSlot}}"];
+ (2) issue an iframe navigation request with the <{iframe/adauctionheaders}> content attribute set to `true`. In this case, the JavaScript code is retrieved as part of the iframe navigation response, at which point the JavaScript code in the iframe makes the call to {{Navigator/runAdAuction()}}, and - |config|["{{AuctionAdConfig/directFromSellerSignalsHeaderAdSlot}}"] can be can be specified + |config|["{{AuctionAdConfig/directFromSellerSignalsHeaderAdSlot}}"] can be specified directly without a Promise. * To parse the value |result|: @@ -1676,14 +1699,15 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. [=list/For each=] |component| in |auctionConfig|'s [=auction config/component auctions=], [=parallel queue/enqueue steps|enqueue the following steps=] to |queue|: 1. If |component|'s [=auction config/server response=] is not null: - 1. Let |compWinnerInfo| be the result of running [=parse and validate server response=] with |component|, - |auctionConfig|, |global|, |bidIgs|, and |bidDebugReportInfoList|. + 1. Let |compWinnerInfo| be the result of running [=parse and validate server response=] with + |component|, |auctionConfig|, |global|, |bidIgs|, and |bidDebugReportInfoList|. 1. Otherwise: 1. Let |compWinnerInfo| be the result of running [=generate and score bids=] with |component|, |auctionConfig|, |global|, |bidIgs|, |bidDebugReportInfoList|, and |realTimeContributionsMap|. - 1. If |compWinnerInfo| is failure, abort these steps. - 1. If [=recursively wait until configuration input promises resolve=] given |auctionConfig| returns - failure, abort these steps. + 1. If [=recursively wait until configuration input promises resolve=] given |auctionConfig| + returns failure, or |compWinnerInfo| is failure, then: + 1. Decrement |pendingComponentAuctions| by 1. + 1. Abort these steps. 1. If |topLevelDirectFromSellerSignalsRetrieved| is false: 1. Let |topLevelDirectFromSellerSignals| be the result of running [=get direct from seller signals=] given |seller|, |auctionConfig|'s @@ -2784,6 +2808,8 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=list=] of [=bid debug report |bidDebugReportInfoList|, perform the following steps. They return a [=leading bid info=] or a failure. 1. [=Assert=] that these steps are running [=in parallel=]. +1. If [=waiting until server response promise resolves=] given |auctionConfig| returns failure, then + return failure. 1. Let |hash| be the [=SHA-256=] of |auctionConfig|'s [=auction config/server response=]. 1. Let |capturedAuctionHeaders| be |global|'s [=associated Document's=] [=node navigable's=] [=traversable navigable's=] [=traversable navigable/captured ad auction result headers=]. @@ -6611,6 +6637,16 @@ a {{Promise}} |p|, and two sequences of steps, covering the parsing of the value 1. Decrement |auctionConfig|'s [=auction config/pending promise count=].
+
+To wait until server response promise resolves given an [=auction config=] |auctionConfig|: + + 1. Wait until either |auctionConfig|'s [=auction config/server response=] is not a {{Promise}}, + or |auctionConfig|'s [=auction config/aborted=] is true. + 1. If |auctionConfig|'s [=auction config/aborted=] is true, return failure. + 1. If |auctionConfig|'s [=auction config/server response=] is failure, return failure. + 1. Return. +
+
To look up per-buyer currency given an [=auction config=] |auctionConfig|, and an [=origin=] |buyer|: