diff --git a/spec.bs b/spec.bs
index 2c0205074..08ddabc42 100644
--- a/spec.bs
+++ b/spec.bs
@@ -89,6 +89,13 @@ spec: private-aggregation-api; urlPrefix: https://patcg-individual-drafts.github
text: debug-details-key; url: #debug-details-key
text: aggregation coordinator; url: #aggregation-coordinator
text: default aggregation coordinator; url: #default-aggregation-coordinator
+ text: privateaggregation; url: #privateaggregation
+ text: batching scope; url: #batching-scope
+ text: debug scope; url: #debug-scope
+ text: scoping details; url: #scoping-details
+ text: contribution cache entry; url: #contribution-cache-entry
+ text: contribution cache; url: #contribution-cache
+ text: default filtering id max bytes; url: #default-filtering-id-max-bytes
spec: Shared Storage API; urlPrefix: https://wicg.github.io/shared-storage
type: dfn
text: shared-storage; url: #permissionspolicy-shared-storage
@@ -793,6 +800,9 @@ The runAdAuction(|config|) method steps are:
1. Let |settings| be [=this=]'s [=relevant settings 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 |privateAggregationAllowed| be the result of determining whether |global|'s [=associated
+ Document=] is [=allowed to use=] the "[=private-aggregation=]
" [=policy-controlled
+ feature=].
1. Let |auctionConfig| be the result of running [=validate and convert auction ad config=] with
|config| and true.
1. If |auctionConfig| is failure, then [=exception/throw=] a {{TypeError}}.
@@ -824,7 +834,7 @@ The runAdAuction(|config|) method steps are:
1. Let |queue| be the result of [=starting a new parallel queue=].
1. [=parallel queue/enqueue steps|Enqueue the following steps=] to |queue|:
1. Let |reportingContextMap| be the result of [=creating a reporting context map=] given
- |auctionConfig|.
+ |auctionConfig| and |privateAggregationAllowed|.
1. If |auctionConfig|'s [=auction config/server response=] is not null:
1. Let |winnerInfo| be the result of running [=parse and validate server response=] with
|auctionConfig|, null, |global|, |bidIgs|, and |reportingContextMap|.
@@ -851,10 +861,13 @@ The runAdAuction(|config|) method steps are:
1. [=Send report=] with |reportUrl| and |settings|.
1. [=Send real time reports=] with |auctionReportInfo|'s
[=auction report info/real time reporting contributions map=] and |settings|.
+ 1. [=Process the Private Aggregation contributions=] given |auctionConfig|,
+ |reportingContextMap|.
1. Otherwise:
1. Let |winner| be |winnerInfo|'s [=leading bid info/leading bid=].
1. Let |fencedFrameConfig| be the result of [=filling in a pending fenced frame config=] with
- |pendingConfig|, |auctionConfig|, |winnerInfo|, |auctionReportInfo|, and |settings|.
+ |pendingConfig|, |auctionConfig|, |reportingContextMap|, |winnerInfo|, |auctionReportInfo|,
+ and |settings|.
1. [=fenced frame config mapping/Finalize a pending config=] on |configMapping| with |urn| and
|fencedFrameConfig|.
1. Wait until |auctionConfig|'s [=auction config/resolve to config=] is a boolean.
@@ -948,8 +961,9 @@ To construct a pending fenced frame config given an [=auction config=
To
fill in a pending fenced frame config given a [=fenced frame config=]
-|pendingConfig|, [=auction config=] |auctionConfig|, [=leading bid info=] |winningBidInfo|,
-[=auction report info=] |auctionReportInfo|, and an [=environment settings object=] |settings|:
+|pendingConfig|, [=auction config=] |auctionConfig|, [=reporting context map=]
+|reportingContextMap|, [=leading bid info=] |winningBidInfo|, [=auction report info=]
+|auctionReportInfo|, and an [=environment settings object=] |settings|:
1. Let |winningBid| be |winningBidInfo|'s [=leading bid info/leading bid=].
1. Let |replacements| be an [=ordered map=] whose [=map/keys=] are [=strings=] and whose
[=map/values=] are [=strings=].
@@ -1020,8 +1034,8 @@ To
fill in a pending fenced frame config given a [=fenced frame confi
1. [=Asynchronously finish reporting=] with |pendingConfig|'s
[=fenced frame config/fenced frame reporting metadata=]'s
[=fenced frame reporting metadata/value=]'s
- [=fenced frame reporting metadata/fenced frame reporting map=], |winningBidInfo|,
- |auctionReportInfo| and |settings|.
+ [=fenced frame reporting metadata/fenced frame reporting map=], |auctionConfig|,
+ |reportingContextMap|, |winningBidInfo|, |auctionReportInfo| and |settings|.
1. Let |adComponentDescriptorsWithReplacements| be a new [=list=] of [=ad descriptors=].
1. If |winningBid|'s [=generated bid/ad component descriptors=] is not null:
1. [=list/For each=] |adComponentDescriptor| of |winningBid|'s
@@ -1042,7 +1056,8 @@ To
fill in a pending fenced frame config given a [=fenced frame confi
To asynchronously finish reporting given a
-[=fencedframetype/fenced frame reporting map=] |reportingMap|, [=leading bid info=] |leadingBidInfo|,
+[=fencedframetype/fenced frame reporting map=] |reportingMap|, [=auction config=] |auctionConfig|,
+[=reporting context map=] |reportingContextMap|, [=leading bid info=] |leadingBidInfo|,
[=auction report info=] |auctionReportInfo|, and an [=environment settings object=] |settings|:
1. [=Increment a winning bid's k-anonymity count=] given |leadingBidInfo|'s [=leading bid info/leading bid=].
1. If |leadingBidInfo|'s [=leading bid info/leading non-k-anon-enforced bid=] is
@@ -1099,6 +1114,7 @@ To asynchronously finish reporting given a
1. [=Send report=] with |report| and |settings|.
1. [=Send real time reports=] with |auctionReportInfo|'s
[=auction report info/real time reporting contributions map=] and |settings|.
+1. [=Process the Private Aggregation contributions=] given |auctionConfig|, |reportingContextMap|.
@@ -1732,10 +1748,11 @@ To
generate potentially multiple bids given an [=ordered map=]-or-nul
a [=string=] |auctionSignals|, a {{BiddingBrowserSignals}} |browserSignals|, a [=string=]-or-null |perBuyerSignals|,
a {{DirectFromSellerSignalsForBuyer}} |directFromSellerSignalsForBuyer|, a [=duration=]
|perBuyerTimeout| in milliseconds, a [=currency tag=] |expectedCurrency|, an {{unsigned short}}
-|multiBidLimit|, an [=interest group=] |ig|, and a [=moment=] |auctionStartTime|, and an
-[=environment settings object=] |settings|, perform the following steps. They return a failure if
-failing to fetch the script or wasm, otherwise a [=tuple=] of ([=list=] of [=generated bids=],
-[=bid debug reporting info=], [=list=] of [=real time reporting contributions=]).
+|multiBidLimit|, an [=interest group=] |ig|, a [=reporting context=] |reportingContext|, a
+[=moment=] |auctionStartTime|, and an [=environment settings object=] |settings|, perform the
+following steps. They return a failure if failing to fetch the script or wasm, otherwise a
+[=tuple=] of ([=list=] of [=generated bids=], [=bid debug reporting info=],
+[=list=] of [=real time reporting contributions=]).
1. Let |igGenerateBid| be the result of [=building an interest group passed to generateBid=] with
|ig|.
1. Set |browserSignals|["{{BiddingBrowserSignals/joinCount}}"] to the sum of |ig|'s
@@ -1792,10 +1809,10 @@ failing to fetch the script or wasm, otherwise a [=tuple=] of ([=list=] of [=gen
1. Let |originKey| be the [=serialization of an origin|serialization=] of
|crossOriginTrustedBiddingSignalsOrigin|.
1. [=map/Set=] |crossOriginTrustedBiddingSignalsOrigin|[|originKey|] to |trustedBiddingSignals|.
- 1. Return the result of [=evaluating a bidding script=] with |biddingScript|, |multiBidLimit|, |ig|, |expectedCurrency|,
- |igGenerateBid|, |auctionSignals|, |perBuyerSignals|, |sameOriginTrustedBiddingSignals|,
- |crossOriginTrustedBiddingSignals|, |browserSignals|, |directFromSellerSignalsForBuyer|.
- and |perBuyerTimeout|.
+ 1. Return the result of [=evaluating a bidding script=] with |biddingScript|, |multiBidLimit|,
+ |ig|, |reportingContext|, |expectedCurrency|, |igGenerateBid|, |auctionSignals|,
+ |perBuyerSignals|, |sameOriginTrustedBiddingSignals|, |crossOriginTrustedBiddingSignals|,
+ |browserSignals|, |directFromSellerSignalsForBuyer| and |perBuyerTimeout|.
@@ -1844,27 +1861,29 @@ 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|[|component|],
+ [=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|[
- |component|], |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|.
1. Decrement |pendingComponentAuctions| by 1.
1. Wait until |pendingComponentAuctions| is 0.
1. If |auctionConfig|'s [=auction config/aborted=] is true, return failure.
+ 1. Set |reportingContextMap|[|auctionConfig|]'s [=reporting context/local leader info=] to
+ a copy of |leadingBidInfo|.
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|.
1. Set |leadingBidInfo|'s [=leading bid info/component seller=] to |winningComponentConfig|'s
[=auction config/seller=].
1. Let « |topLevelSellerSignals|, unusedTopLevelReportResultBrowserSignals » be the result of
- running [=report result=] with |leadingBidInfo|, |topLevelDirectFromSellerSignalsForSeller|,
- |winningComponentConfig|, and |global|.
+ running [=report result=] with |leadingBidInfo|, |reportingContextMap|[|auctionConfig|],
+ |topLevelDirectFromSellerSignalsForSeller|, |winningComponentConfig|, and |global|.
1. Set |leadingBidInfo|'s [=leading bid info/auction config=] to |winningComponentConfig|.
1. Set |leadingBidInfo|'s [=leading bid info/component seller=] to null.
1. Set |leadingBidInfo|'s [=leading bid info/top level seller=] to |seller|.
@@ -1880,9 +1899,15 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
|leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/interest group=]'s
[=interest group/owner=].
1. Let « |sellerSignals|, |reportResultBrowserSignals| » be the result of running
- [=report result=] with |leadingBidInfo|, |directFromSellerSignalsForSeller|, null, and |global|.
- 1. Run [=report win=] with |leadingBidInfo|, |sellerSignals|, |reportResultBrowserSignals|,
- |directFromSellerSignalsForBuyer|, and |settings|.
+ [=report result=] with |leadingBidInfo|, |reportingContextMap|[|winningComponentConfig|],
+ |directFromSellerSignalsForSeller|, null, and |global|.
+ 1. Run [=report win=] with |leadingBidInfo|, |reportingContextMap|[|winningComponentConfig|],
+ |sellerSignals|, |reportResultBrowserSignals|, |directFromSellerSignalsForBuyer|,
+ and |settings|.
+ 1. Set |reportingContextMap|[|auctionConfig|]'s [=reporting context/winner reporting id=] to
+ |leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/reporting id=].
+ 1. Set |reportingContextMap|[|winningComponentConfig|]'s [=reporting context/winner reporting id=]
+ to |leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/reporting id=].
1. Return |leadingBidInfo|.
1. If [=waiting until configuration input promises resolve=] given |auctionConfig| returns failure,
@@ -1906,6 +1931,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
|browserSignals|["{{BiddingBrowserSignals/requestedSize}}"] to the result of running
[=convert an ad size to a map=] with |auctionConfig|'s [=auction config/requested size=].
1. Let |auctionLevel| be "single-level-auction".
+1. Let |reportingContext| be |reportingContextMap|[|auctionConfig|].
1. Let |componentAuctionExpectedCurrency| be null.
1. If |topLevelAuctionConfig| is not null:
1. [=map/Set=] |browserSignals|["{{BiddingBrowserSignals/topLevelSeller}}"]] to the
@@ -1919,7 +1945,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
|auctionConfig|, |topLevelAuctionConfig|, |negativeTargetInfo|, |reportingContextMap| and |global|.
1. Let |pendingAdditionalBids| be the [=list/size=] of |additionalBids|.
1. [=list/For each=] |additionalBid| of |additionalBids|, run the following steps [=in parallel=]:
- 1. [=Score and rank a bid=] with |auctionConfig|, |reportingContextMap|[|auctionConfig|],
+ 1. [=Score and rank a bid=] with |auctionConfig|, |reportingContext|
|additionalBid|'s [=decoded additional bid/bid=], |leadingBidInfo|, |decisionLogicFetcher|,
|trustedScoringSignalsBatcher|, |directFromSellerSignalsForSeller|, null, |auctionLevel|,
|componentAuctionExpectedCurrency|, |topLevelOrigin|, and |realTimeContributionsMap|.
@@ -2026,12 +2052,13 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
|allTrustedBiddingSignals|, |crossOriginTrustedBiddingSignalsOrigin|, |auctionSignals|,
a [=map/clone=] of |browserSignals|, |perBuyerSignals|,
|directFromSellerSignalsForBuyer|, |perBuyerTimeout|, |expectedCurrency|,
- |multiBidLimit|, |ig|, |auctionStartTime|, and |settings|.
+ |multiBidLimit|, |ig|, |reportingContext|, |auctionStartTime|, and |settings|.
1. If |generateBidResult| is failure, then:
1. If |optedInForRealTimeReporting| is true, then [=add a platform contribution=] with
[=bidding script failure bucket=], |realTimeContributionsMap| and |buyer|.
1. [=iteration/Continue=].
- 1. Let (|bidsBatch|, |bidDebugReportInfo|, |realTimeContributions|) be |generateBidResult|.
+ 1. Let (|bidsBatch|, |bidDebugReportInfo|, |realTimeContributions|, |paContributions|) be
+ |generateBidResult|.
1. Let |generateBidDuration| be the [=duration from=] |generateBidStartTime| to |settings|'s
[=environment settings object/current monotonic time=], in milliseconds.
1. If |perBuyerCumulativeTimeout| is not null, decrement |perBuyerCumulativeTimeout| by
@@ -2055,11 +2082,13 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
|perBuyerTimeout| to |perBuyerCumulativeTimeout|.
1. Let |generateBidStartTime| be |settings|'s
[=environment settings object/current monotonic time=].
- 1. Set (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|) to the result
- of running [=generate potentially multiple bids=] with |allTrustedBiddingSignals|,
+ 1. Set (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|,
+ |paContributions|) to the result of running [=generate potentially multiple bids=]
+ with |allTrustedBiddingSignals|,
|crossOriginTrustedBiddingSignalsOrigin|, |auctionSignals|, a [=map/clone=] of |browserSignals|,
|perBuyerSignals|, |directFromSellerSignalsForBuyer|, |perBuyerTimeout|, |expectedCurrency|,
- 1 (for multiBidLimit), |kAnonRestrictedIG|, |auctionStartTime|, and |settings|.
+ 1 (for multiBidLimit), |kAnonRestrictedIG|, |reportingContext|, |auctionStartTime|,
+ and |settings|.
Note: passing 1 for multiBidLimit limits the rerun to producing at most a single bid.
@@ -2072,32 +2101,35 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. [=Assert=] that [=query generated bid k-anonymity count=] given |generatedBid| returns true.
1. [=Apply any component ads target to a bid=] given |generatedBid|.
1. [=list/Append=] |generatedBid| to |bidsToScore|.
- 1. [=Register bids for forDebuggingOnly reports=] given |bidsToScore|, |ig|,
- |bidDebugReportInfo|, and |reportingContextMap|[|auctionConfig|].
+ 1. [=Register bids for reporting=] given |bidsToScore|, |ig|, |bidDebugReportInfo|,
+ |paContributions|, and |reportingContext|.
1. If |auctionConfig|'s [=auction config/per buyer real time reporting config=][|buyer|]
is "`default-local-reporting`", then [=insert entries to map=] given
|realTimeContributionsMap|, |buyer|, and |realTimeContributions|.
1. [=list/For each=] |bidToScore| of |bidsToScore|:
1. If |bidToScore|'s [=generated bid/for k-anon auction=] is true,
[=list/append=] |bidToScore|'s [=generated bid/interest group=] to |bidIgs|.
- 1. [=Score and rank a bid=] with |auctionConfig|, |reportingContextMap|[
- |auctionConfig|], |bidToScore|, |leadingBidInfo|,
- |decisionLogicFetcher|, |trustedScoringSignalsBatcher|,
+ 1. [=Score and rank a bid=] with |auctionConfig|, |reportingContext|, |bidToScore|,
+ |leadingBidInfo|, |decisionLogicFetcher|, |trustedScoringSignalsBatcher|,
|directFromSellerSignalsForSeller|, |dataVersion|, |auctionLevel|,
|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. Set |reportingContext|'s [=reporting context/local leader info=] to |leadingBidInfo|.
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
- [=report result=] with |leadingBidInfo|, |directFromSellerSignalsForSeller|, null, and |global|.
+ [=report result=] with |leadingBidInfo|, |reportingContext|, |directFromSellerSignalsForSeller|,
+ null, and |global|.
1. Let |directFromSellerSignalsForWinner| be the result of running
[=get direct from seller signals for a buyer=] with |directFromSellerSignals|, and
|leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/interest group=]'s
[=interest group/owner=].
- 1. Run [=report win=] with |leadingBidInfo|, |sellerSignals|, |reportResultBrowserSignals|,
- |directFromSellerSignalsForWinner|, and |settings|.
+ 1. Run [=report win=] with |leadingBidInfo|, |reportingContext|, |sellerSignals|,
+ |reportResultBrowserSignals|, |directFromSellerSignalsForWinner|, and |settings|.
+ 1. Set |reportingContext|'s [=reporting context/winner reporting id=] to |leadingBidInfo|'s
+ [=leading bid info/leading bid=]'s [=generated bid/reporting id=].
1. Let |replacements| be an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=]
are [=strings=].
1. [=list/For each=] [=ad keyword replacement=], |replacement|, within
@@ -2322,9 +2354,9 @@ or "component-auction", a [=currency tag=] |componentAuctionExpectedCurrency|, a
"`default-local-reporting`", then [=add a platform contribution=] with
[=scoring script failure bucket=], |realTimeContributionsMap| and |seller|.
1. Return.
-1. Let « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions| » be
- the result of [=evaluating a scoring script=] with |decisionLogicScript|, |adMetadata|,
- |bidValue|'s [=bid with currency/value=], |auctionConfig|'s [=auction config/config idl=],
+1. Let « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions|,
+ |paContributions| » be the result of [=evaluating a scoring script=] with |decisionLogicScript|,
+ |adMetadata|, |bidValue|'s [=bid with currency/value=], |auctionConfig|, |reportingContext|,
|sameOriginTrustedScoringSignals|, |crossOriginTrustedScoringSignals|, |browserSignals|,
|directFromSellerSignalsForSeller|, and |auctionConfig|'s [=auction config/seller timeout=].
1. If |generatedBid|'s [=generated bid/for k-anon auction=] is true:
@@ -2352,6 +2384,8 @@ or "component-auction", a [=currency tag=] |componentAuctionExpectedCurrency|, a
1. If |auctionConfig|'s [=auction config/seller real time reporting config=] is
"`default-local-reporting`", then [=insert entries to map=] given |realTimeContributionsMap|,
|seller|, and |realTimeContributions|.
+ 1. [=Commit private aggregation contributions=] given |paContributions|, |generatedBid|'s
+ [=generated bid/reporting id=] and |reportingContext|.
1. Let |scoreAdOutput| be result of [=processing scoreAd output=] with |scoreAdResult|.
1. Return if any of the following conditions hold:
* |scoreAdOutput| is failure;
@@ -2770,8 +2804,9 @@ To
get direct from seller signals for a buyer given a
To report result given a [=leading bid info=] |leadingBidInfo|, a
-[=direct from seller signals=]-or-null |directFromSellerSignals|, an [=auction config=]-or-null
-|winningComponentConfig|, and a [=global object=] |global|:
+[=reporting context=] |reportingContext|, a [=direct from seller signals=]-or-null
+|directFromSellerSignals|, an [=auction config=]-or-null |winningComponentConfig|,
+and a [=global object=] |global|:
1. Let |config| be |leadingBidInfo|'s [=leading bid info/auction config=].
1. Let |bidCurrency| be null.
1. If |winningComponentConfig| is not null:
@@ -2859,9 +2894,11 @@ To report result given a [=leading bid info=] |leadingBidInfo|, a
|config|'s [=auction config/decision logic url=] and |global|'s [=relevant settings object=].
1. Let |sellerReportingScript| be the result of [=waiting for script body from a fetcher=] given
|sellerReportingScriptFetcher|.
- 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored » be the result of
- [=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`", |config|'s
- [=auction config/config idl=]'s {{AuctionAdConfig/reportingTimeout}}, and
+ 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored, |paContributions| » be the
+ result of [=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`",
+ |reportingContext|, |config|'s [=auction config/seller=], |config|'s [=auction config/seller
+ Private Aggregation coordinator=], |config|'s [=auction config/config idl=]'s
+ {{AuctionAdConfig/reportingTimeout}}, and
« |config|'s [=auction config/config idl=], |browserSignals|, |directFromSellerSignals| ».
1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]:
: [=reporting result/report url=]
@@ -2873,6 +2910,8 @@ To report result given a [=leading bid info=] |leadingBidInfo|, a
[=leading bid info/component seller reporting result=] to |reportingResult|.
1. Otherwise, set |leadingBidInfo|'s [=leading bid info/seller reporting result=] to
|reportingResult|.
+ 1. [=Commit private aggregation contributions=] given |paContributions|, |winner|'s [=generated
+ bid/reporting id=] and |reportingContext|.
1. [=map/Remove=] |browserSignals|["`desirability`"].
1. [=map/Remove=] |browserSignals|["`modifiedBid`"].
1. [=map/Remove=] |browserSignals|["`topLevelSellerSignals`"].
@@ -2885,7 +2924,8 @@ To report result given a [=leading bid info=] |leadingBidInfo|, a
-To
report win given a [=leading bid info=] |leadingBidInfo|, a [=string=] |sellerSignals|,
+To
report win given a [=leading bid info=] |leadingBidInfo|, [=reporting context=]
+|reportingContext|, a [=string=] |sellerSignals|,
a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=]-or-null
|directFromSellerSignals|, and an [=environment settings object=] |settings|:
@@ -2914,8 +2954,8 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=]
|winner|'s [=generated bid/modeling signals=] if it is not null, {{undefined}} otherwise
(TODO: noise and bucket this signal)
- 1. Let |igAd| be the [=interest group ad=] from |winner|'s
- [=generated bid/interest group=]'s [=interest group/ads=] whose
+ 1. Let |ig| be |winner|'s [=generated bid/interest group=].
+ 1. Let |igAd| be the [=interest group ad=] from ig's [=interest group/ads=] whose
[=interest group ad/render url=] is |winner|'s
[=generated bid/ad descriptor=]'s [=ad descriptor/url=].
1. If |winner|'s [=generated bid/selected buyer and seller reporting ID=] is not null:
@@ -2953,13 +2993,16 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=]
1. Let |reportFunctionName| be "`reportWin`".
1. If |winner|'s [=generated bid/provided as additional bid=] is true:
1. Set |reportFunctionName| be "`reportAdditionalBidWin`".
- 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap| » be the result of
- [=evaluating a reporting script=] with |buyerReportingScript|, "`reportWin`", |leadingBidInfo|'s
- [=leading bid info/auction config=]'s [=auction config/config idl=]'s
- {{AuctionAdConfig/reportingTimeout}}, and
+ 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap|, |paContributions| » be
+ the result of [=evaluating a reporting script=] with |buyerReportingScript|, "`reportWin`",
+ |reportingContext|, |ig|'s [=interest group/owner=], |ig|'s [=interest group/Private Aggregation
+ coordinator=], |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config
+ idl=]'s {{AuctionAdConfig/reportingTimeout}}, and
« |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config idl=]'s
{{AuctionAdConfig/auctionSignals}}, |perBuyerSignalsForBuyer|, |sellerSignals|,
|reportWinBrowserSignals|, |directFromSellerSignals| ».
+ 1. [=Commit private aggregation contributions=] given |paContributions|, |winner|'s [=generated
+ bid/reporting id=] and |reportingContext|.
1. Set |leadingBidInfo|'s [=leading bid info/buyer reporting result=] to a [=reporting result=]
with the following [=struct/items=]:
: [=reporting result/report url=]
@@ -3564,6 +3607,25 @@ A reporting context is a [=struct=] with the following [=struct/items
: debug reporting info
:: A [=map=] from [=reporting bid key=] to [=bid debug reporting info=].
+ : private aggregation batching scope map
+ :: A [=map=] from a [=tuple=] consisting of an origin (an
+ [=origin=]) and a coordinator (an [=aggregation
+ coordinator=]) to a [=batching scope=].
+
+ Note: Does not include [=batching scopes=] for contributions conditional on
+ non-reserved events.
+ : private aggregation on event contributions
+ :: A [=map=] from a tuple of ([=reporting bid key=], [=string=]) to a [=list=] of [=on event
+ contribution entries=].
+ : private aggregation allowed
+ :: A [=boolean=], initially false.
+ : local leader info
+ :: A [=leading bid info=], describing information on what, if anything, won the particular
+ auction this [=reporting context=] is for.
+ : winner reporting id
+ :: A [=reporting bid key=] or null, initially null. This can be null even if [=reporting context/
+ local leader info=] has a leader set, in case this context is for a component auction that lost
+ at top-level.
A reporting context map is a [=map=] from [=auction config=] to [=reporting context=].
@@ -3571,16 +3633,45 @@ Here the keys are configurations for auctions that actually produce bids (e.g. n
auction in a multi-party auction).
- To create a reporting context map given [=auction config=] |auctionConfig|:
+ To create a reporting context map given the [=auction config=] |auctionConfig| and
+ a [=boolean=] |privateAggregationAllowed|:
1. Let |reportingContextMap| be a new [=reporting context map=].
- 1. If |auctionConfig|'s [=auction config/component auctions=] [=list/is empty=],
- [=map/set=] |reportingContextMap|[|auctionConfig|] to a new [=reporting context=].
- 1. Otherwise, [=list/for each=] |component| in |auctionConfig|'s
+ 1. [=map/Set=] |reportingContextMap|[|auctionConfig|] to a new [=reporting context=].
+ 1. [=list/For each=] |component| in |auctionConfig|'s
[=auction config/component auctions=], [=map/set=] |reportingContextMap|[|component|] to a new
[=reporting context=].
+ 1. [=map/For each=] _ → |reportingContext| of |reportingContextMap|:
+ 1. Set |reportingContext|'s [=reporting context/private aggregation allowed=] to
+ |privateAggregationAllowed|
1. Return |reportingContextMap|.
+
+ To register bids for reporting given a [=list=] of
+ [=generated bids=] |generatedBids|, [=interest group=] |ig|, [=bid debug reporting info=]
+ |bidDebugReportInfo|, a [=Private Aggregation contributions=] |paContributions| and a [=reporting
+ context=] |reportingContext|:
+ 1. Let |id| be a new [=reporting bid key=] with the following [=struct/items=]:
+ : [=reporting bid key/context=]
+ :: |reportingContext|
+
+ : [=reporting bid key/source=]
+ :: [=reporting bid source/generate-bid=]
+
+ : [=reporting bid key/bidder origin=]
+ :: |ig|'s [=interest group/owner=]
+
+ : [=reporting bid key/bid identifier=]
+ :: |ig|'s [=interest group/name=]
+ 1. [=map/Set=] |reportingContext|'s [=reporting context/debug reporting info=][|id|] to
+ |bidDebugReportInfo|.
+ 1. [=Commit private aggregation contributions=] given |paContributions|, |id| and
+ |reportingContext|.
+ 1. [=list/For each=] |generatedBid| of |generatedBids|:
+ 1. Set |generatedBid|'s [=generated bid/reporting id=] to |id|.
+
+
+
## {{InterestGroupBiddingAndScoringScriptRunnerGlobalScope/forDebuggingOnly}} ## {#for-debugging-only-header}
*This first introductory paragraph is non-normative.*
@@ -3654,29 +3745,6 @@ methods for event-level forDebuggingOnly reports for winning and losi
1. Return |auctionReportInfo|.
-
- To register bids for forDebuggingOnly reports given a [=list=] of
- [=generated bids=] |generatedBids|, [=interest group=] |ig|, [=bid debug reporting info=]
- |bidDebugReportInfo| and a [=reporting context=] |reportingContext|:
- 1. Let |id| be a new [=reporting bid key=] with the following [=struct/items=]:
- : [=reporting bid key/context=]
- :: |reportingContext|
-
- : [=reporting bid key/source=]
- :: [=reporting bid source/generate-bid=]
-
- : [=reporting bid key/bidder origin=]
- :: |ig|'s [=interest group/owner=]
-
- : [=reporting bid key/bid identifier=]
- :: |ig|'s [=interest group/name=]
- 1. [=map/Set=] |reportingContext|'s [=reporting context/debug reporting info=][|id|] to
- |bidDebugReportInfo|.
- 1. [=list/For each=] |generatedBid| of |generatedBids|:
- 1. Set |generatedBid|'s [=generated bid/reporting id=] to |id|.
-
-
-
### Downsampling ### {#downsampling-header}
*This first introductory paragraph is non-normative.*
@@ -3961,6 +4029,398 @@ RAPPOR noises each coordinate of the bit vector independently, and it is par
1. Return |histogram|.
+## {{InterestGroupScriptRunnerGlobalScope/privateAggregation}} ## {#private-aggregation-reporting-header}
+
+*This first introductory paragraph is non-normative.*
+
+For metrics that can be interpreted as histograms aggregated over the entire population, Protected
+Audience provides integration with the [Private Aggregation API](https://github.com/patcg-individual-drafts/private-aggregation-api).
+In addition to its {{PrivateAggregation/contributeToHistogram(contribution)}} method, the API is
+extended with contributeToHistogramOnEvent(event, contribution)
+which permits histogram contributions to be conditional and to incorporate values not accessible to
+the running script, like values of auction winning bids and various performance metrics.
+
+Signal base value
+A signal base value is one of the following:
+
+: "winning-bid
"
+:: The numeric value is the bid value of the winning bid.
+: "highest-scoring-other-bid
"
+:: The numeric value is the bid value of the highest scoring bid that did not
+ win.
+: "script-run-time
"
+:: The numeric value is the number of milliseconds of CPU time the calling
+ function (e.g. `generateBid()`) took to run.
+: "signals-fetch-time
"
+:: The numeric value is the number of milliseconds it took for the trusted
+ bidding or scoring signals fetch to complete, when called from
+ `generateBid()` or `scoreAd()`, respectively. In other functions it evaluates to 0.
+: "bid-reject-reason
"
+:: 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=].
+
+
+
+On event contribution entry
+An on event contribution entry is a [=struct=] with the following items:
+
+: contribution
+:: A {{PAExtendedHistogramContribution}}
+: batching scope
+:: A [=batching scope=] or null
+: debug scope
+:: A [=debug scope=]
+: debug details
+:: A [=debug details=] or null (default null)
+
+
+
+Worklet function
+A worklet function is one of the following:
+
+: "generate-bid
"
+:: The `generateBid()` function.
+: "score-ad
"
+:: The `scoreAd()` function.
+: "report-result
"
+:: The `reportResult()` function.
+: "report-win
"
+:: The `reportWin()` function.
+
+
+
+Private Aggregation contributions
+Private Aggregation contributions is a [=map=] from [=string=] to a [=list=] of [=on event
+contribution entries=].
+
+### Algorithms ### {#private-aggregation-algorithms}
+
+
+To
prepare for private aggregation given a
+{{InterestGroupScriptRunnerGlobalScope}} |global|, a [=reporting context=] |reportingContext|,
+and [=origins=] |origin| and |aggregationCoordinator|:
+1. Let |debugScope| be a new [=debug scope=].
+1. Set |global|'s [=InterestGroupScriptRunnerGlobalScope/private aggregation=] to a new
+ [=PrivateAggregation=] with the following [=struct/items=]:
+ :
allowed to use
+ :: |reportingContext|'s [=reporting context/private aggregation allowed=].
+ :
scoping details
+ :: a new [=scoping details=] with the [=struct/items=]:
+ :
get batching scope steps
+ :: An algorithm that performs the following steps:
+ 1. If |aggregationCoordinator| is null, set |aggregationCoordinator| to
+ the [=default aggregation coordinator=].
+ 1. Return the result of running [=get or create a batching scope=] given
+ |origin|, |aggregationCoordinator| and |reportingContext|.
+ :
get debug scope steps
+ :: An algorithm that returns |debugScope|.
+
+
+
+
+To
finalize private aggregation debug info given a
+{{InterestGroupScriptRunnerGlobalScope}} |global|:
+ 1. Let |debugScope| be the result of running |global|'s {{InterestGroupScriptRunnerGlobalScope/
+ privateAggregation}}'s
+
scoping details's
+
get debug scope steps.
+ 1. Let |debugDetails| be the result of [=get a debug details=] given |debugScope|.
+ 1. Let |onEventContributionMap| be |global|'s [=InterestGroupScriptRunnerGlobalScope/on event
+ contribution map=].
+ 1. [=map/For each=]
event → |entries| of |onEventContributionMap|:
+ 1. [=list/For each=] |onEventEntry| of |entries|:
+ 1. If |onEventEntry|'s [=on event contribution entry/debug scope=] is |debugScope|,
+ set |onEventEntry|'s [=on event contribution entry/debug details=] to |debugDetails|.
+ 1. [=Mark a debug scope complete=] given |debugScope|.
+
+
+
+To extract private aggregation contributions given a
+{{InterestGroupScriptRunnerGlobalScope}} |global|:
+ 1. Return |global|'s [=InterestGroupScriptRunnerGlobalScope/on event contribution map=].
+
+Issue: TODO: regular histograms need to work the same way, too, so they get discarded for k-anon
+runs; this method exists as an abstraction to help add that.
+
+
+
+To commit private aggregation contributions given an [=Private Aggregation
+contributions=] |onEventMap|, a [=reporting bid key=] |bidKey|, and a [=reporting context=]
+|reportingContext|:
+ 1. [=map/For each=] |event| → |contributions| of |onEventMap|:
+ 1. Let |key| be (|bidKey|, |event|).
+ 1. If |reportingContext|'s [=reporting context/private aggregation on event contributions=][|key|]
+ does not [=map/exist=], set it to a new [=list=].
+ 1. [=list/Extend=] |reportingContext|'s [=reporting context/private aggregation on event
+ contributions=][|key|] with |contributions|.
+
+
+
+To get or create a batching scope given an [=origin=] |origin|, an
+[=aggregation coordinator=] |aggregationCoordinator| and a [=reporting context=] |reportingContext|,
+perform the following steps. They return a [=batching scope=].
+1. Let |batchingScopeMap| be |reportingContext|'s [=reporting context/private aggregation
+ batching scope map=].
+1. Let |tuple| be (|origin|, |aggregationCoordinator|).
+1. If |batchingScopeMap|[|tuple|] does not [=map/exist=]:
+ 1. Set |batchingScopeMap|[|tuple|] to a new [=batching scope=].
+ 1. If |aggregationCoordinator| is not null, [=set the aggregation coordinator for a batching
+ scope=] given |aggregationCoordinator| and |batchingScopeMap|[|tuple|].
+1. Return |batchingScopeMap|[|tuple|].
+
+
+
+
+To process the Private Aggregation contributions given an [=auction config=]
+|auctionConfig| and a [=reporting context map=] |reportingContextMap|:
+
+1. [=Process the Private Aggregation contributions for an auction=] given |auctionConfig|,
+ |reportingContextMap|[|auctionConfig|].
+1. [=list/For each=] |componentAuction| in |auctionConfig|'s [=auction config/component
+ auctions=]:
+ 1. [=Process the Private Aggregation contributions for an auction=] given |componentAuction|,
+ |reportingContextMap|[|componentAuction|].
+
+
+
+
+To
process the Private Aggregation contributions for an auction 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=].
+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. [=list/For each=] |onEventEntry| of |contributions|:
+ 1. Let |filledInContribution| be the result of [=filling in the contribution=] given
+ |onEventEntry|'s [=on event contribution entry/contribution=] and |leadingBidInfo|.
+
+ Issue: Once
WICG/turtledove#627
+ is resolved, align 'filling in' logic with `forDebuggingOnly`.
+
+ 1. If |event| does not [=string/start with=] "`reserved.`":
+ 1. Store |event|, |filledInContribution|, |onEventEntry|'s [=on event contribution entry/debug
+ details=] in the {{FencedFrameConfig}} as appropriate.
+
+ Note: Each non-reserved |event| will have a different [=batching scope=].
+
+ Issue: Once
WICG/turtledove#616
+ and any successors are landed, align integration and fill in fenced frame's
+
report a private aggregation event.
+ 1. Otherwise:
+ 1. Let |entry| be a new [=contribution cache entry=] with the items:
+ :
contribution
+ :: |filledInContribution|
+ :
batching scope
+ :: |onEventEntry|'s [=on event contribution entry/batching scope=]
+ :
debug scope
+ :: |onEventEntry|'s [=on event contribution entry/debug scope=]
+ :
debug details
+ :: |onEventEntry|'s [=on event contribution entry/debug details=]
+ 1. [=Append an entry to the contribution cache|Append=] |entry| to the [=contribution cache=].
+1. Let |sellerBatchingScope| be the result of [=get or create a batching
+ scope|getting or creating a batching scope=] given |auctionConfig|'s [=auction config/seller=],
+ |auctionConfig|'s [=auction config/seller Private Aggregation coordinator=], and
+ |reportingContext|.
+1. Let |auctionReportBuyersDebugScope| be a new [=debug scope=].
+1. [=map/For each=] |reportType| → |reportBuyerConfig| of |auctionConfig|'s
+ [=auction config/auction report buyers=]:
+ 1. [=map/For each=] |buyerOrigin| → |buyerOffset| of |auctionConfig|'s
+ [=auction config/auction report buyer keys=]:
+ 1. Let |bucket| be the sum of |buyerOffset| and |reportBuyerConfig|'s
+ {{AuctionReportBuyersConfig/bucket}}.
+
+ Issue: Handle overflow here or in validation. See
WICG/turtledove#1040.
+ 1. Let |value| be the result (a {{double}}) of switching on
+ |reportType|:
+
+ : "`interestGroupCount`"
+ :: The number of interest groups in the [=user agent=]'s interest group set whose owner is
+ |buyerOrigin|.
+ : "`bidCount`"
+ :: The number of valid bids generated by interest groups whose owner is
+ |buyerOrigin|.
+ : "`totalGenerateBidLatency`"
+ :: The sum of execution time in milliseconds for all `generateBid()`
+ calls in the auction for interest groups whose owner is
+ |buyerOrigin|.
+ : "`totalSignalsFetchLatency`"
+ :: The total time spent fetching trusted buyer signals in
+ milliseconds, or 0 if the interest group didn't fetch any
+ trusted signals.
+ : None of the above values
+ :: [=Assert=]: false, as this enum value is validated in [=validate and convert auction
+ ad config=]
+
+
+
+ Issue: More formally spec the values here.
+
+ 1. Set |value| to the result of multiplying |reportBuyerConfig|'s
+ {{AuctionReportBuyersConfig/scale}} with |value|.
+ 1. Set |value| to the maximum of 0.0 and |value|.
+ 1. Set |value| to the result of converting |value| to an integer by
+ truncating its fractional part.
+ 1. Set |value| to the minimum of |value| and 2
31−1.
+ 1. Let |contribution| be a new {{PAHistogramContribution}} with the
+ items:
+ : {{PAHistogramContribution/bucket}}
+ :: |bucket|
+ : {{PAHistogramContribution/value}}
+ :: |value|
+ : {{PAHistogramContribution/filteringId}}
+ :: 0
+
+ Issue: Consider allowing the filtering ID to be set here.
+ 1. [=map/For each=] |ig| of the [=user agent=]'s
+ interest group set whose
+
owner is |buyerOrigin|:
+ 1. If seller capabilities of |ig| don't allow this reporting, [=iteration/continue=].
+
+ Issue: Align behavior with seller capabilities handling once
+ WICG/turtledove#966 is resolved.
+ 1. Let |entry| be a new [=contribution cache entry=] with the items:
+ :
contribution
+ :: |contribution|
+ :
batching scope
+ :: |sellerBatchingScope|
+ :
debug scope
+ :: |auctionReportBuyersDebugScope|
+ 1. [=Append an entry to the contribution cache|Append=] |entry| to
+ the [=contribution cache=].
+1. [=Mark a debug scope complete=] given |auctionReportBuyersDebugScope| and
+ |auctionConfig|'s [=auction config/auction report buyer debug details=].
+1. [=map/For each=] (|origin|,
aggregationCoordinator) →
+ |batchingScope| of |reportingContext|'s [=reporting context/private aggregation batching
+ scope map=]:
+ 1. [=Process contributions for a batching scope=] given |batchingScope|, |origin|,
+ "
protected-audience
" and null.
+
+
+
+
+To fill in the contribution given a {{PAExtendedHistogramContribution}} |contribution|
+and a [=leading bid info=] |leadingBidInfo|, perform the following steps. They return a
+{{PAHistogramContribution}}:
+1. Let |bucket| be |contribution|["{{PAExtendedHistogramContribution/bucket}}"].
+1. If |bucket| is a {{PASignalValue}}, set |bucket| to the result of [=filling
+ in the signal value=] given |bucket|, 2128−1 and |leadingBidInfo|.
+1. Let |value| be |contribution|["{{PAExtendedHistogramContribution/value}}"].
+1. If |value| is a {{PASignalValue}}, set |value| to the result of [=filling in
+ the signal value=] given |value|, 231−1 and |leadingBidInfo|.
+1. Let |filledInContribution| be a new {{PAHistogramContribution}} with the
+ items:
+ : {{PAHistogramContribution/bucket}}
+ :: |bucket|
+ : {{PAHistogramContribution/value}}
+ :: |value|
+ : {{PAHistogramContribution/filteringId}}
+ :: |contribution|["{{PAExtendedHistogramContribution/filteringId}}"]
+1. Return |filledInContribution|.
+
+
+
+
+To fill in the signal value given a {{PASignalValue}} |value|, an
+integer |maxAllowed| and a [=leading bid info=] |leadingBidInfo|, perform the following steps.
+They return an integer.
+1. [=Assert=]: |value|["{{PASignalValue/baseValue}}"] is a valid [=signal base
+ value=].
+1. Let |returnValue| be the result of [=determining a signal's numeric value=]
+ given |value|["{{PASignalValue/baseValue}}"] and |leadingBidInfo|.
+1. If |value|["{{PASignalValue/scale}}"] [=map/exists=], set |returnValue| to
+ the result of multiplying |value|["{{PASignalValue/scale}}"] with
+ |returnValue|.
+1. Set |returnValue| to the result of converting |returnValue| to an integer by
+ truncating its fractional part.
+1. If |value|["{{PASignalValue/offset}}"] [=map/exists=], set |returnValue| to
+ the result of adding |returnValue| to |value|["{{PASignalValue/offset}}"].
+1. Clamp |returnValue| to [=the inclusive range|the range=] 0 to |maxAllowed|,
+ inclusive, and return the result.
+
+
+
+
+
+To
determine a signal's numeric value given a [=signal base value=]
+|signalBaseValue| and a [=leading bid info=] |leadingBidInfo|, perform the following steps.
+They return a {{double}}.
+1. If |signalBaseValue| is "
[=signal base value/winning-bid=]
":
+ 1. If |leadingBidInfo|'s [=leading bid info/leading bid=] is null, return 0.
+ 1. Otherwise, return |leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/bid=].
+1. If |signalBaseValue| is
+ "
[=signal base value/highest-scoring-other-bid=]
":
+ 1. If |leadingBidInfo|'s [=leading bid info/highest scoring other bid=] is null, return 0.
+ 1. Otherwise, return |leadingBidInfo|'s [=leading bid info/highest scoring other bid=]'s
+ [=generated bid/bid=].
+1. If |signalBaseValue| is "
[=signal base value/script-run-time=]
":
+ 1. Return the number of milliseconds of CPU time that the calling function
+ (e.g. `generateBid()`) took to run.
+1. If |signalBaseValue| is "
[=signal base value/signals-fetch-time=]
":
+ Switch on the associated [=worklet function=]:
+
+ : [=worklet function/generate-bid=]
+ :: Return the number of milliseconds it took for the trusted bidding signals
+ fetch to complete, or 0 if no fetch was made.
+ : [=worklet function/score-ad=]
+ :: Return the number of milliseconds it took for the trusted scoring signals
+ fetch to complete or 0 if no fetch was made.
+ : [=worklet function/report-result=]
+ : [=worklet function/report-win=]
+ :: Return 0.
+
+
+1. If |signalBaseValue| is "
[=signal base value/bid-reject-reason=]
":
+ 1. If the bid did not succeed purely because it didn't meet the required
+
k-anonymity threshold, return 8.
+ 1. Let |bidRejectReason| be "`not-available`".
+ 1. If the seller provided a reject reason, set |bidRejectReason| to that
+ value.
+ 1. If |bidRejectReason| is:
+
+ : "`not-available`"
+ :: Return 0.
+ : "`invalid-bid`"
+ :: Return 1.
+ : "`bid-below-auction-floor`"
+ :: Return 2.
+ : "`pending-approval-by-exchange`"
+ :: Return 3.
+ : "`disapproved-by-exchange`"
+ :: Return 4.
+ : "`blocked-by-publisher`"
+ :: Return 5.
+ : "`language-exclusions`"
+ :: Return 6.
+ : "`category-exclusions`"
+ :: Return 7.
+ : None of the above values
+ :: [=Assert=]: false
+
+ Note: this enum value is validated in `scoreAd()`.
+
+ Issue: Verify this once
+ WICG/turtledove#627 is resolved.
+
+ Issue: There are some automatically generated values that are not described here.
+
+ Issue: Verify handling when the bid was not rejected.
+
+
+
+
+
## Get storage interest groups for owner ## {#get-storage-interest-groups-for-owner-header}
*This first introductory paragraph is non-normative.*
@@ -4837,14 +5297,15 @@ of the following global objects:
To evaluate a bidding script given a [=string=] |script|, an {{unsigned short}}
- |multiBidLimit|, an [=interest group=] |ig|, a [=currency tag=] |expectedCurrency|,
- a {{GenerateBidInterestGroup}} |igGenerateBid|, a [=string=]-or-null
- |auctionSignals|, a [=string=]-or-null |perBuyerSignals|, an [=ordered map=]-or-null
- |sameOriginTrustedBiddingSignals|, an [=ordered map=]-or-null |crossOriginTrustedBiddingSignals|,
- a {{BiddingBrowserSignals}} |browserSignals|, a {{DirectFromSellerSignalsForBuyer}}
- |directFromSellerSignalsForBuyer|, and an integer millisecond [=duration=] |timeout|, perform the
- following steps. They return a [=tuple=] ([=list=] of [=generated bids=],
- [=bid debug reporting info=], [=list=] of [=real time reporting contributions=]).
+ |multiBidLimit|, an [=interest group=] |ig|, a [=reporting context=] |reportingContext|,
+ a [=currency tag=] |expectedCurrency|, a {{GenerateBidInterestGroup}} |igGenerateBid|,
+ a [=string=]-or-null |auctionSignals|, a [=string=]-or-null |perBuyerSignals|,
+ an [=ordered map=]-or-null |sameOriginTrustedBiddingSignals|, an [=ordered map=]-or-null
+ |crossOriginTrustedBiddingSignals|, a {{BiddingBrowserSignals}} |browserSignals|,
+ a {{DirectFromSellerSignalsForBuyer}} |directFromSellerSignalsForBuyer|, and an integer
+ millisecond [=duration=] |timeout|, perform the following steps. They return a [=tuple=] ([=list=]
+ of [=generated bids=], [=bid debug reporting info=], [=list=] of [=real time reporting
+ contributions=]).
1. Let |realm| be the result of [=creating a new script runner realm=] given
{{InterestGroupBiddingScriptRunnerGlobalScope}}.
@@ -4857,6 +5318,8 @@ of the following global objects:
[=InterestGroupBiddingScriptRunnerGlobalScope/group has ad components=] to true if |ig|'s
[=interest group/ad components=] is not null, or false otherwise.
1. Set |global|'s [=InterestGroupBiddingScriptRunnerGlobalScope/expected currency=] to |expectedCurrency|.
+ 1. [=Prepare for private aggregation=] given |global|, |reportingContext|, |ig|'s [=interest
+ group/owner=] and |ig|'s [=interest group/Private Aggregation coordinator=].
1. Let |isComponentAuction| be true if |browserSignals|["{{BiddingBrowserSignals/topLevelSeller}}"] is not null, or
false otherwise.
1. Set |global|'s [=InterestGroupBiddingScriptRunnerGlobalScope/is component auction=] to
@@ -4928,20 +5391,31 @@ of the following global objects:
1. If |contribution|'s [=real time reporting contribution/latency threshold=] is not null, and
≥ |duration|, then [=iteration/continue=].
1. [=list/Append=] |contribution| to |realTimeContributions|.
- 1. Return a [=tuple=] (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|).
+ 1. [=Finalize private aggregation debug info=] given |global|.
+ 1. Let |paContributions| be the result of [=extracting private aggregation contributions=] given
+ |global|.
+ 1. Return a [=tuple=] (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|,
+ |paContributions|).
To evaluate a scoring script given a [=string=] |script|, a [=string=] |adMetadata|,
- a {{double}} |bidValue|, an {{AuctionAdConfig}} |auctionConfigIDL|, an [=ordered map=]-or-null
- |sameOriginTrustedScoringSignals|, an [=ordered map=]-or-null |crossOriginTrustedScoringSignals|,
+ a {{double}} |bidValue|, an [=auction config=] |auctionConfig|, a [=reporting context=]
+ |reportingContext|, an [=ordered map=]-or-null |sameOriginTrustedScoringSignals|,
+ an [=ordered map=]-or-null |crossOriginTrustedScoringSignals|,
{{ScoringBrowserSignals}} |browserSignals|, a {{DirectFromSellerSignalsForSeller}}
|directFromSellerSignalsForSeller|, and an integer millisecond [=duration=] |timeout|:
1. Let |realm| be the result of [=creating a new script runner realm=] given
{{InterestGroupScoringScriptRunnerGlobalScope}}.
+ 1. Let |global| be |realm|'s [=realm/global object=].
+ 1. Let |settings| be |realm|'s [=realm/settings object=].
+ 1. [=Prepare for private aggregation=] given |global|, |reportingContext|, |auctionConfig|'s
+ [=auction config/seller=] and |auctionConfig|'s [=auction config/seller Private Aggregation
+ coordinator=].
1. Let |browserSignalsJS| be |browserSignals| [=converted to ECMAScript values=].
- 1. Let |auctionConfigJS| be |auctionConfigIDL| [=converted to ECMAScript values=].
+ 1. Let |auctionConfigJS| be |auctionConfig|'s [=auction config/config idl=] [=converted to
+ ECMAScript values=].
1. Let |sameOriginTrustedScoringSignalsJS| be |sameOriginTrustedScoringSignals|
[=converted to ECMAScript values=].
1. Let |crossOriginTrustedScoringSignalsJS| be |crossOriginTrustedScoringSignals|
@@ -4967,17 +5441,24 @@ of the following global objects:
1. If |contribution|'s [=real time reporting contribution/latency threshold=] is not null, and
≥ |duration|, then [=iteration/continue=].
1. [=list/Append=] |contribution| to |realTimeContributions|.
- 1. Return « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions| ».
+ 1. [=Finalize private aggregation debug info=] given |global|.
+ 1. Let |paContributions| be the result of [=extracting private aggregation contributions=] given
+ |global|.
+ 1. Return « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions|,
+ |paContributions| ».
To evaluate a reporting script given a [=string=] |script|, a [=string=]
- |functionName|, an integer millisecond [=duration=] |timeout|, and a [=list=] of arguments
- |arguments|:
+ |functionName|, a [=reporting context=] |reportingContext|, an [=origin=] |origin|, an
+ [=origin=] |privateAggregationCoordinator|, an integer millisecond [=duration=] |timeout|,
+ and a [=list=] of arguments |arguments|:
1. Let |realm| be the result of [=creating a new script runner realm=] given
{{InterestGroupReportingScriptRunnerGlobalScope}}.
1. Let |global| be |realm|'s [=realm/global object=].
+ 1. [=Prepare for private aggregation=] given |global|, |reportingContext|, |origin|, and
+ |privateAggregationCoordinator|.
1. Let |argumentsJS| be the result of [=converting a Web IDL arguments list to an ECMAScript
arguments list|converting=] |arguments| to an ECMAScript arguments list. If this
[=exception/throws=] an exception, return « "null", null, null, null ».
@@ -4994,8 +5475,12 @@ of the following global objects:
1. If |reportURL| is failure, set |reportURL| to null.
1. Let |macroMap| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=]
if |functionName| is "`reportWin`" or "`reportAdditionalBidWin`", null otherwise.
+ 1. [=Finalize private aggregation debug info=] given |global|.
+ 1. Let |paContributions| be the result of [=extracting private aggregation contributions=] given
+ |global|.
1. Return « |resultJSON|, |reportURL|,
- |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=], |macroMap| ».
+ |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=], |macroMap|,
+ |paContributions| ».
@@ -5062,10 +5547,113 @@ specification are those that explicitly list the global names provided here.
[Exposed=InterestGroupScriptRunnerGlobalScope]
interface InterestGroupScriptRunnerGlobalScope {
+ readonly attribute PrivateAggregation? privateAggregation;
+};
+
+dictionary PASignalValue {
+ required DOMString baseValue;
+ double scale;
+ (bigint or long) offset;
+};
+
+dictionary PAExtendedHistogramContribution {
+ required (PASignalValue or bigint) bucket;
+ required (PASignalValue or long) value;
+ bigint filteringId = 0;
+};
+
+[Exposed=InterestGroupScriptRunnerGlobalScope]
+partial interface PrivateAggregation {
+ undefined contributeToHistogramOnEvent(
+ DOMString event, PAExtendedHistogramContribution contribution);
};
+Each {{InterestGroupScriptRunnerGlobalScope}} has a
+
+ : private aggregation
+ :: Null, or a [=PrivateAggregation=]. Initially null.
+ : on event contribution map
+ :: A [=map=] from [=string=] to a [=list=] of [=on event contribution entries=].
+
+
+
+The privateAggregation [=getter
+ steps=] are:
+
+ 1. Return [=this=]'s [=relevant global object=]'s
+ [=InterestGroupScriptRunnerGlobalScope/private aggregation=].
+
+
+
+The
contributeToHistogramOnEvent(DOMString
+event, PAExtendedHistogramContribution contribution) method steps are:
+1. If [=this=]'s
+ allowed to use is false, [=exception/throw=] a {{TypeError}}.
+1. Let |scopingDetails| be [=this=]'s
+ scoping details
+1. If |event| [=string/starts with=] "`reserved.`" and « "`reserved.always`",
+ "`reserved.loss`", "`reserved.win`" » does not [=list/contain=] |event|,
+ return.
+
+ Note: No error is thrown to allow forward compatibility if additional
+ reserved event types are added later.
+1. Let |bucket| be |contribution|["{{PAExtendedHistogramContribution/bucket}}"].
+1. If |bucket| is a {{PASignalValue}}:
+ 1. If |bucket|["{{PASignalValue/baseValue}}"] is not a valid [=signal base
+ value=], [=exception/throw=] a {{TypeError}}.
+ 1. If |bucket|["{{PASignalValue/offset}}"] is not a {{bigint}}, [=exception/
+ throw=] a {{TypeError}}.
+1. Otherwise, if |contribution|["{{PAExtendedHistogramContribution/bucket}}"] is
+ not [=set/contained=] in [=the exclusive range|the range=] 0 to
+ 2
128, exclusive, [=exception/throw=] a {{TypeError}}.
+
+ Issue: Make the error type consistent with
+ {{PrivateAggregation/contributeToHistogram(contribution)}}.
+1. Let |value| be |contribution|["{{PAExtendedHistogramContribution/value}}"].
+1. If |value| is a {{PASignalValue}}:
+ 1. If |value|["{{PASignalValue/baseValue}}"] is not a valid [=signal base
+ value=], [=exception/throw=] a {{TypeError}}.
+ 1. If |value|["{{PASignalValue/offset}}"] is a {{bigint}}, [=exception/
+ throw=] a {{TypeError}}.
+1. Otherwise, if |contribution|["{{PAExtendedHistogramContribution/value}}"] is
+ negative, [=exception/throw=] a {{TypeError}}.
+1. If |contribution|["{{PAExtendedHistogramContribution/filteringId}}"] is
+ not [=set/contained=] in [=the exclusive range|the range=] 0 to
+ 256
[=default filtering ID max bytes=], exclusive, [=exception/
+ throw=] a {{TypeError}}.
+
+ Issue: Make the error types on validation issues here and above consistent
+ with {{PrivateAggregation/contributeToHistogram(contribution)}}.
+
+ Note: It is not currently possible to set a non-default filtering ID max
+ bytes for Protected Audience.
+1. Let |batchingScope| be null.
+1. If |event| [=string/starts with=] "`reserved.`", set |batchingScope| to the
+ result of running |scopingDetails|'
+ get batching scope steps.
+
+ Note: Each non-reserved |event| will have a different [=batching scope=]
+ that is created later.
+1. Let |entry| be a new [=on event contribution entry=] with the items:
+ : [=on event contribution entry/contribution=]
+ :: |contribution|
+ : [=on event contribution entry/batching scope=]
+ :: |batchingScope|
+ : [=on event contribution entry/debug scope=]
+ :: The result of running |scopingDetails|'
get debug scope steps.
+
+1. Let |global| be [=this=]'s [=relevant global object=].
+1. Let |onEventContributionMap| be |global|'s
+ [=InterestGroupScriptRunnerGlobalScope/on event contribution map=].
+1. If |onEventContributionMap|[|event|] does not [=map/exist=], set
+ |onEventContributionMap|[|event|] to a new [=list=].
+1. [=list/Append=] |entry| to |onEventContributionMap|[|event|].
+
+
+
[Exposed=InterestGroupBiddingAndScoringScriptRunnerGlobalScope]
interface ForDebuggingOnly {