-
Notifications
You must be signed in to change notification settings - Fork 240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Spec] Add private aggregation support for B&A response #1344
base: main
Are you sure you want to change the base?
Changes from all commits
4aa9ce1
c0ca394
7a31945
3eea6aa
6389de6
44b043d
7ec9717
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1870,13 +1870,13 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: | |
[=get direct from seller signals for a seller=] given |topLevelDirectFromSellerSignals|. | ||
1. Set |topLevelDirectFromSellerSignalsRetrieved| to true. | ||
1. If |compWinnerInfo|'s [=leading bid info/leading bid=] is not null, then run | ||
[=score and rank a bid=] with |auctionConfig|, |reportingContextMap|[auctionConfig], | ||
[=score and rank a bid=] with |auctionConfig|, |reportingContextMap|[|auctionConfig|], | ||
|compWinnerInfo|'s [=leading bid info/leading bid=], |leadingBidInfo|, | ||
|decisionLogicFetcher|, |trustedScoringSignalsBatcher|, null, "top-level-auction", null, | ||
and |topLevelOrigin|. | ||
1. If |compWinnerInfo|'s [=leading bid info/leading non-k-anon-enforced bid=] | ||
is not null, then run [=score and rank a bid=] with |auctionConfig|, |reportingContextMap|[ | ||
auctionConfig], |compWinnerInfo|'s [=leading bid info/leading non-k-anon-enforced bid=], | ||
|auctionConfig|], |compWinnerInfo|'s [=leading bid info/leading non-k-anon-enforced bid=], | ||
|leadingBidInfo|, |decisionLogicFetcher|, |trustedScoringSignalsBatcher|, | ||
|topLevelDirectFromSellerSignalsForSeller|, null, "top-level-auction", null, |topLevelOrigin|, | ||
and |realTimeContributionsMap|. | ||
|
@@ -3137,17 +3137,20 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=reporting context map=] | |
[=bid debug reporting info/bidder debug loss report url=] to |maybeDebugReportUrl|. | ||
1. Set |bidDebugReportingInfo|'s [=bid debug reporting info/server filtered debugging only reports=] | ||
to [=server auction response/server filtered debugging only reports=]. | ||
1. Set |reportingContextMap|[|auctionConfig|]'s [=reporting context/debug reporting info=] to | ||
1. Let |reportingContext| be |reportingContextMap|[|auctionConfig|]. | ||
1. Set |reportingContext|'s [=reporting context/debug reporting info=] to | ||
|bidDebugReportingInfo|. | ||
1. Let |reportingId| be a [=reporting bid key=] with the following [=struct/items=]: | ||
: [=reporting bid key/context=] | ||
:: |reportingContextMap|[|auctionConfig|] | ||
:: |reportingContext| | ||
: [=reporting bid key/source=] | ||
:: [=reporting bid source/bidding-and-auction-services=] | ||
: [=reporting bid key/bidder origin=] | ||
:: |response|'s [=server auction response/interest group owner=] | ||
: [=reporting bid key/bid identifier=] | ||
:: |response|'s [=server auction response/interest group name=] | ||
1. [=Handle server response private aggregation fields=] given |response|, |requestContext| and | ||
|reportingId|. | ||
1. Let |winningBid| be a new [=generated bid=] with the following [=struct/items=]: | ||
: [=generated bid/reporting id=] | ||
:: |reportingId| | ||
|
@@ -3247,6 +3250,69 @@ a [=list=] of [=interest groups=] |bidIgs|, and a [=reporting context map=] | |
|
||
</div> | ||
|
||
<div algorithm> | ||
To <dfn>handle server response private aggregation fields</dfn> given a [=server auction response=] | ||
|response|, a [=reporting context=] |reportingContext|, and a [=reporting bid key=] |reportingId|: | ||
|
||
1. [=Assert=] that these steps are running [=in parallel=]. | ||
1. [=Commit server response private aggregation contributions=] given |response|'s | ||
[=server auction response/component win private aggregation contributions=], |reportingContext|, | ||
|reportingId| and false. | ||
1. [=Commit server response private aggregation contributions=] given |response|'s | ||
[=server auction response/server filtered private aggregation reserved contributions=], | ||
|reportingContext|, |reportingId| and true. | ||
1. [=Commit server response private aggregation contributions=] given |response|'s | ||
[=server auction response/server filtered private aggregation non reserved contributions=], | ||
|reportingContext|, |reportingId| and true. | ||
|
||
</div> | ||
|
||
<div algorithm> | ||
To <dfn>commit server response private aggregation contributions</dfn> given a | ||
[=server auction response=] |contributionsMap|, a [=reporting context=] |reportingContext|, a | ||
[=reporting bid key=] |reportingId| and a [=boolean=] |serverFiltered|: | ||
|
||
1. [=map/For each=] (|reportingOrigin|, |coordinator|, |event|) → |contributions| of |contributionsMap|: | ||
1. Let |eventToContributionsMap| be a new [=Private Aggregation contributions=]. | ||
1. Let |scopingDetails| be a new [=scoping details=] with the [=struct/items=]: | ||
: <a spec="private-aggregation-api" for="scoping details">get batching scope steps</a> | ||
:: An algorithm that performs the following steps: | ||
1. If |coordinator| is null, set |coordinator| to the [=default aggregation coordinator=]. | ||
1. Return the result of running [=get or create a batching scope=] given |reportingOrigin|, | ||
|coordinator| and |reportingContext|. | ||
: <a spec="private-aggregation-api" for="scoping details">get debug scope steps</a> | ||
:: An algorithm that returns a new [=debug scope=]. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So technically you don't need a |scopingDetails| here since you're not integrating with contributeToHistogram[OnEvent], though it might be worthwhile for consistency? |
||
|
||
1. Let |batchingScope| be null. | ||
1. If |event| [=string/starts with=] "`reserved.`", set |batchingScope| to the | ||
result of running |scopingDetails|' <a spec="private-aggregation-api" for="scoping details"> | ||
get batching scope steps</a>. | ||
|
||
Note: Each non-reserved |event| will have a different [=batching scope=] | ||
that is created later. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is copied from on-device PAgg part. I don't see a place that creates the batching scope for non-reserved events, IIUC There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it may be because those are sent, well, on event? |
||
1. [=list/For each=] |contribution| of |contributions|: | ||
1. Let |entry| be a new [=on event contribution entry=] with the items: | ||
: [=on event contribution entry/contribution=] | ||
:: |contribution| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to have some sort of an assert here that it doesn't have any baseValues? |
||
: [=on event contribution entry/batching scope=] | ||
:: |batchingScope| | ||
: [=on event contribution entry/debug scope=] | ||
:: The result of running |scopingDetails|' <a spec="private-aggregation-api" | ||
for="scoping details">get debug scope steps</a>. | ||
: [=on event contribution entry/worklet function=] | ||
:: "`generate-bid`" (it does not matter for server returned contributions) | ||
: [=on event contribution entry/server filtered=] | ||
:: |serverFiltered| | ||
: [=on event contribution entry/origin=] | ||
:: |reportingOrigin| | ||
1. If |eventToContributionsMap|[|event|] does not [=map/exist=], set | ||
|eventToContributionsMap|[|event|] to « |entry| ». | ||
1. Otherwise, [=list/append=] |eventToContributionsMap|[|event|] with |entry|. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ....append ... with ... is kinda strange. Append |entry| to ... ? |
||
1. [=Commit private aggregation contributions=] given |eventToContributionsMap|, |reportingId| and | ||
|reportingContext|. | ||
|
||
</div> | ||
|
||
<h3 id="canloadadauctionfencedframe">canLoadAdAuctionFencedFrame()</h3> | ||
|
||
*This first introductory paragraph is non-normative.* | ||
|
@@ -3478,6 +3544,20 @@ A <dfn>server auction response</dfn> is a [=struct=] that contains auction resul | |
:: Null or [=server auction reporting info=]. | ||
: <dfn>component seller reporting</dfn> | ||
:: Null or [=server auction reporting info=]. | ||
: <dfn>component win private aggregation contributions</dfn> | ||
:: A [=map=] whose [=map/keys=] are ([=reporting bid key=], [=string=]), and whose [=map/values=] | ||
are [=lists=] of [=on event contribution entries=]. Private aggregation contributions from | ||
winners of component auctions run on trusted auction servers. These need to be filtered by the | ||
client based on the top level auction's outcome. | ||
: <dfn>server filtered private aggregation reserved contributions</dfn> | ||
:: A [=map=] from a tuple of ([=reporting bid key=], [=string=]) to a [=list=] of [=on event | ||
contribution entries=]. Server filtered private aggregation contributions with reserved event | ||
types (already set to "reserved.always"), which are not dependent on the final auction result and | ||
should always be reported. | ||
: <dfn>server filtered private aggregation non reserved contributions</dfn> | ||
:: A [=map=] from a tuple of ([=reporting bid key=], [=string=]) to a [=list=] of [=on event | ||
contribution entries=]. Server filtered private aggregation contributions with non reserved event | ||
types, which are not dependent on the final auction result and should always be reported. | ||
: <dfn>component win debugging only reports</dfn> | ||
:: A [=map=] whose [=map/keys=] are [=server auction debug report keys=], and whose [=map/values=] | ||
are [=lists=] of [=urls=]. | ||
|
@@ -3531,18 +3611,22 @@ The <dfn for=Navigator method>getInterestGroupAdAuctionData(|configIDL|)</dfn> m | |
1. Set |config|'s [=auction data config/encryption key=] to |key|. | ||
1. Set |config|'s [=auction data config/encryption key id=] to |keyId|. | ||
1. Let |igMap| be a new [=map=] whose [=map/keys=] are [=origins=] and [=map/values=] are [=lists=]. | ||
1. Let |igPAggCoordinatorMap| be a new [=map=] whose [=map/keys=] are tuples of ([=origins=], [=strings=]) | ||
and [=map/values=] are [=origins=]. | ||
1. Let |startTime| be a [=moment=] equal to the [=current coarsened wall time=]. | ||
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. Let |name| be |ig|'s [=interest group/name=]. | ||
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|. | ||
1. Let |components| be a new [=list=]. | ||
1. [=list/For each=] |component| in |ig|'s [=interest group/ad components=], [=list/append=] |component|'s [=interest group ad/ad render ID=] to |components|. | ||
1. [=list/For each=] |component| in |ig|'s [=interest group/ad components=], [=list/append=] | ||
|component|'s [=interest group ad/ad render ID=] to |components|. | ||
1. Let |prevWins| be a new <code>[=sequence=]<[=server auction previous win=]></code>. | ||
1. [=list/For each=] |prevWin| of |ig|'s [=interest group/previous wins=] for all days within the | ||
the last 30 days: | ||
|
@@ -3567,7 +3651,7 @@ The <dfn for=Navigator method>getInterestGroupAdAuctionData(|configIDL|)</dfn> m | |
:: |prevWins| | ||
1. Let |serverIg| be a new [=server auction interest group=] with the following [=struct/items=]: | ||
: [=server auction interest group/name=] | ||
:: |ig|'s [=interest group/name=] | ||
:: |name| | ||
: [=server auction interest group/bidding signals keys=] | ||
:: |ig|'s [=interest group/trusted bidding signals keys=] | ||
: [=server auction interest group/user bidding signals=] | ||
|
@@ -3581,11 +3665,13 @@ The <dfn for=Navigator method>getInterestGroupAdAuctionData(|configIDL|)</dfn> m | |
: [=server auction interest group/priority=] | ||
:: |ig|'s [=interest group/priority=] | ||
1. [=list/Append=] |serverIg| to |igMap|[|owner|]. | ||
1. If |ig|'s [=interest group/Private Aggregation coordinator=] is not null, then [=map/set=] | ||
|igPAggCoordinatorMap|[(|owner|, |name|)] to it. | ||
1. Let |result| be a new {{AdAuctionData}}. | ||
1. Let |requestId| be the [=string representation=] of a [=version 4 UUID=]. | ||
1. [=map/Set=] |result|["{{AdAuctionData/requestId}}"] to |requestId|. | ||
1. Let (|requestBlob|, |context|) be the result of serializing |igMap| using | ||
|config|. The serialization method may follow that described in | ||
1. Let (|requestBlob|, |context|) be the result of serializing |igMap| with |config| and | ||
|igPAggCoordinatorMap|. The serialization method may follow that described in | ||
[Section 2.2.4 of Bidding and Auction Services](https://privacysandbox.github.io/draft-ietf-bidding-and-auction-services/draft-ietf-bidding-and-auction-services.html#name-generating-a-request). | ||
1. Set |result|["{{AdAuctionData/request}}"] to |requestBlob|. | ||
1. [=Queue a global task=] on the [=DOM manipulation task source=], given |global|, to | ||
|
@@ -4206,8 +4292,7 @@ A signal base value is one of the following: | |
: "<dfn><code>bid-reject-reason</code></dfn>" | ||
:: The numeric value is an integer representing the reason a bid was rejected. | ||
|
||
Note: this mapping to an integer is defined in [=determine a signal's | ||
numeric value=]. | ||
Note: this mapping to an integer is defined in [=determine a signal's numeric value=]. | ||
|
||
: "<dfn><code>average-code-fetch-time</code></dfn>" | ||
:: The numeric value is the average time it took to fetch code resources (JavaScript or WebAssembly) | ||
|
@@ -4258,6 +4343,9 @@ An on event contribution entry is a [=struct=] with the following items: | |
:: A [=debug details=] or null (default null) | ||
: <dfn>worklet function</dfn> | ||
:: A [=worklet function=]. | ||
: <dfn>server filtered</dfn> | ||
:: A [=boolean=], initially false. Only set to true when the contribution is already filtered by the | ||
trusted auction server before sent back to the client. | ||
: <dfn>origin</dfn> | ||
:: The [=origin=] of the script that contributed the entry. | ||
|
||
|
@@ -4423,7 +4511,7 @@ runs; this method exists as an abstraction to help add that. | |
</div> | ||
|
||
<div algorithm> | ||
To <dfn>commit private aggregation contributions</dfn> given an [=Private Aggregation | ||
To <dfn>commit private aggregation contributions</dfn> given a [=Private Aggregation | ||
contributions=] |onEventMap|, a [=reporting bid key=] |bidKey|, and a [=reporting context=] | ||
|reportingContext|: | ||
1. [=map/For each=] |event| → |contributions| of |onEventMap|: | ||
|
@@ -4465,6 +4553,7 @@ To <dfn>process the Private Aggregation contributions</dfn> given an [=auction c | |
<div algorithm> | ||
To <dfn>process the Private Aggregation contributions for an auction</dfn> given | ||
an [=auction config=] |auctionConfig| and a [=reporting context=] |reportingContext|: | ||
|
||
1. If |auctionConfig|'s [=auction config/aborted=] is true, return. | ||
1. Let |winnerId| be |reportingContext|'s [=reporting context/winner reporting id=] | ||
1. Let |leadingBidInfo| be |reportingContext|'s [=reporting context/local leader info=]. | ||
|
@@ -4474,11 +4563,15 @@ an [=auction config=] |auctionConfig| and a [=reporting context=] |reportingCont | |
1. Let |sellerOnceRep| be null. | ||
1. If |reportingContext|'s [=reporting context/seller participants=] [=set/is not empty=], | ||
set |sellerOnceRep| to a random [=set/item=] of [=reporting context/seller participants=]. | ||
1. [=map/For each=] (|bidId|, |event|) → |contributions| of | ||
|reportingContext|'s [=reporting context/private aggregation on event contributions=]: | ||
1. If |event| is "`reserved.win`" or does not [=string/start with=] "`reserved.`": | ||
1. If |bidId| is not |winnerId|, [=iteration/continue=]. | ||
1. If |event| is "`reserved.loss`" and |bidId| is |winnerId|, [=iteration/continue=]. | ||
1. [=map/For each=] (|bidId|, |event|) → |contributions| of |reportingContext|'s | ||
[=reporting context/private aggregation on event contributions=]: | ||
1. If |event| does not [=string/start with=] "`reserved.`": | ||
1. [=list/For each=] |onEventEntry| of |contributions|: | ||
1. If |onEventEntry|'s [=on event contribution entry/server filtered=] is false and |bidId| is | ||
not |winnerId|, then [=list/remove=] |onEventEntry| from |contributions|. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I would prefer if you checked it inside the existing loop over contributions, and just used continue as everything else, rather than have a different pre-filtering loop. |
||
1. If |onEventEntry|'s [=on event contribution entry/server filtered=] is false: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...and you don't even have onEventEntry at this level? I think you probably just want to move the reserved.win/reserved.loss check into the "For each onEventEntry of contributions :" loop, since now it needs to check the server filtered bit.... except shouldn't things that are server-filtered only be using reserved.always anyway? ...I am not sure you actually need the server-filtered bid if the part about them always having reserved.always are true. (The way losing components is supposed to be handled is by not having a winnerId be set on them). |
||
1. If |event| is "`reserved.win`" and |bidId| is not |winnerId|, then [=iteration/continue=]. | ||
1. If |event| is "`reserved.loss`" and |bidId| is |winnerId|, [=iteration/continue=]. | ||
1. [=list/For each=] |onEventEntry| of |contributions|: | ||
1. If |event| is "`reserved.once`": | ||
1. If |onEventEntry|'s [=on event contribution entry/worklet function=] is [=worklet function/ | ||
|
@@ -6042,6 +6135,8 @@ event, PAExtendedHistogramContribution contribution)</dfn> method steps are: | |
reserved event types are added later. | ||
1. If |event| is "`reserved.once`" and |function| is [=worklet function/report-result=] or | ||
[=worklet function/report-win=], [=exception/throw=] a {{TypeError}}. | ||
1. If |event| does not [=string/start with=] "`reserved.`", and |function| is "`scoreAd()`" or | ||
"`report-result`", return. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not understand this change. |
||
1. Let |bucket| be |contribution|["{{PAExtendedHistogramContribution/bucket}}"]. | ||
1. If |bucket| is a {{PASignalValue}}: | ||
1. If |bucket|["{{PASignalValue/baseValue}}"] is not a valid [=signal base | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think server auction response is the right type here?