diff --git a/spec.bs b/spec.bs
index 8f20be548..2cfca488c 100644
--- a/spec.bs
+++ b/spec.bs
@@ -1653,6 +1653,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. Let |auctionStartTime| be the [=current wall time=].
1. Let |decisionLogicFetcher| be the result of [=creating a new script fetcher=] with
|auctionConfig|'s [=auction config/decision logic url=] and |settings|.
+1. Let |trustedScoringSignalsBatcher| be the result of [=creating a trusted scoring signals
+ 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. Let |leadingBidInfo| be a new [=leading bid info=].
@@ -1682,12 +1684,13 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. If |compWinnerInfo|'s [=leading bid info/leading bid=] is not null, then run
[=score and rank a bid=] with |auctionConfig|, |compWinnerInfo|'s
[=leading bid info/leading bid=], |leadingBidInfo|, |decisionLogicFetcher|,
- null, "top-level-auction", null, and |topLevelOrigin|.
+ |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|,
|compWinnerInfo|'s [=leading bid info/leading non-k-anon-enforced bid=],
- |leadingBidInfo|, |decisionLogicFetcher|, |topLevelDirectFromSellerSignalsForSeller|, null,
- "top-level-auction", null, |topLevelOrigin|, and |realTimeContributionsMap|.
+ |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 |leadingBidInfo|'s [=leading bid info/leading bid=] is null, return null.
@@ -1753,8 +1756,9 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
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|, |additionalBid|, |leadingBidInfo|,
- |decisionLogicFetcher|, |directFromSellerSignalsForSeller|, null, |auctionLevel|,
- |componentAuctionExpectedCurrency|, |topLevelOrigin|, and |realTimeContributionsMap|.
+ |decisionLogicFetcher|, |trustedScoringSignalsBatcher|, |directFromSellerSignalsForSeller|,
+ null, |auctionLevel|, |componentAuctionExpectedCurrency|, |topLevelOrigin|, and
+ |realTimeContributionsMap|.
1. Decrement |pendingAdditionalBids| by 1.
1. [=map/For each=] |buyer| → |perBuyerGenerator| of |bidGenerators|,
[=parallel queue/enqueue steps|enqueue the following steps=] to |queue|:
@@ -1928,7 +1932,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
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|, |bidToScore|, |leadingBidInfo|,
- |decisionLogicFetcher|, |directFromSellerSignalsForSeller|, |dataVersion|, |auctionLevel|,
+ |decisionLogicFetcher|, |trustedScoringSignalsBatcher|,
+ |directFromSellerSignalsForSeller|, |dataVersion|, |auctionLevel|,
|componentAuctionExpectedCurrency|, |topLevelOrigin|, and |realTimeContributionsMap|.
1. Decrement |pendingBuyers| by 1.
1. Wait until both |pendingBuyers| and |pendingAdditionalBids| are 0.
@@ -2020,12 +2025,12 @@ To convert to an AuctionAd sequence given a [=list=]-or-null |ads|:
-To
fetch and decode trusted scoring signals given an [=auction config=] |auctionConfig|,
-a [=generated bid=] |generatedBid|, a [=script fetcher=] |decisionLogicFetcher|, an [=origin=]
-|topLevelOrigin|, a [=real time reporting contributions map=] |realTimeContributionsMap|, and a
-[=policy container=] |policyContainer|:
+To
fetch and decode trusted scoring signals given a [=trusted scoring signals batcher=]
+|batcher|, an [=auction config=] |auctionConfig|, a [=generated bid=] |generatedBid|, a
+[=script fetcher=] |decisionLogicFetcher|, an [=origin=] |topLevelOrigin|, a [=real time reporting
+contributions map=] |realTimeContributionsMap|, and a [=policy container=] |policyContainer|:
-1. Let |crossOriginTrustedScoringSignalsOrigin| be null.
+1. Let |isCrossOrigin| be false.
1. Let |sameOriginTrustedScoringSignals| be null.
1. Let |crossOriginTrustedScoringSignals| be null.
1. Let |scoringDataVersion| be null.
@@ -2037,48 +2042,41 @@ a [=generated bid=] |generatedBid|, a [=script fetcher=] |decisionLogicFetcher|,
descriptors=]:
1. [=list/Append=] [=URL serializer|serialized=] |adComponentDescriptor|'s [=ad descriptor/url=]
to |adComponentRenderURLs|.
-1. Let |fullSignalsUrl| be null.
1. If |auctionConfig|'s [=auction config/trusted scoring signals url=] is not null:
- 1. Set |fullSignalsUrl| be the result of [=building trusted scoring signals url=] with |auctionConfig|'s
- [=auction config/trusted scoring signals url=], «|renderURL|», |adComponentRenderURLs|,
- |auctionConfig|'s [=auction config/seller experiment group id=], and |topLevelOrigin|.
-
- Implementations may batch
trusted scoring signals
- requests with same [=auction config/trusted scoring signals url=], |auctionConfig|'s
- [=auction config/seller experiment group id=], and |topLevelOrigin| by collecting render URLs
- and ad component render URLs from multiple invocations of [=score and rank a bid=] and passing
- them all to a single invocation of [=building trusted scoring signals url=] to get a
- |scoringSignalsUrl|. Requests may not be combined if the resulting combination's
- [=string/length=] of [=URL serializer|serialized=] |scoringSignalsUrl| exceeds the [=auction
- config/max trusted scoring signals url length=] of the auction; however this limit does not
- apply if no combining has taken place.
-
- The network response has to be parsed to pull out the pieces relevant to each
- [=evaluating a scoring script|evaluation of a scoring script=].
-
- These requests may also begin before the script fetch, but requests cross-origin to the
- script origin must not happen until [:Ad-Auction-Allow-Trusted-Scoring-Signals-From:] header on
- the script is received, parsed, and determined to authorize such a fetch.
- 1. If |fullSignalsUrl|'s [=url/origin=] is not [=same origin=] with |auctionConfig|'s
- [=auction config/seller=], then:
- 1. Set |crossOriginTrustedScoringSignalsOrigin| to |fullSignalsUrl|'s [=url/origin=].
- 1. Let |allowCrossOriginTrustedScoringSignalsFrom| be the result of [=wait for cross origin
- trusted scoring signals authorization from a fetcher=] given |decisionLogicFetcher|.
- 1. If |allowCrossOriginTrustedScoringSignalsFrom| does not [=list/contain=]
- |crossOriginTrustedScoringSignalsOrigin|:
- 1. Set |crossOriginTrustedScoringSignalsOrigin| to null.
- 1. Set |fullSignalsUrl| to null.
-1. Let |seller| be |auctionConfig|'s [=auction config/seller=].
-1. If |fullSignalsUrl| is not null:
- 1. Let |allTrustedScoringSignals| be null.
- 1.
Set «|allTrustedScoringSignals|,
-
ignored, |scoringDataVersion|» to the result of [=fetching trusted signals=]
- with |fullSignalsUrl|, |auctionConfig|'s [=auction config/seller=], |policyContainer|, and false.
- 1. If |allTrustedScoringSignals| is null, and |auctionConfig|'s
- [=auction config/seller real time reporting config=] is "`default-local-reporting`",then:
- 1. [=Add a platform contribution=] with [=trusted scoring signals failure bucket=],
- |realTimeContributionsMap|, and |seller|.
- 1. Otherwise if |allTrustedScoringSignals| is an [=ordered map=]:
+ 1. Let |request| be a new [=trusted scoring signals request=] with the following [=struct/items=]:
+ : [=trusted scoring signals request/seller=]
+ :: |auctionConfig|'s [=auction config/seller=]
+
+ : [=trusted scoring signals request/seller script fetcher=]
+ :: |decisionLogicFetcher|
+
+ : [=trusted scoring signals request/base url=]
+ :: |auctionConfig|'s [=auction config/trusted scoring signals url=]
+
+ : [=trusted scoring signals request/seller experiment group id=]
+ :: |auctionConfig|'s [=auction config/seller experiment group id=]
+
+ : [=trusted scoring signals request/top level origin=]
+ :: |topLevelOrigin|
+
+ : [=trusted scoring signals request/render URL=]
+ :: |renderURL|
+
+ : [=trusted scoring signals request/ad component URLs=]
+ :: |adComponentRenderURLs|
+
+ : [=trusted scoring signals request/policy container=]
+ :: |policyContainer|
+
+ 1. If |auctionConfig|'s [=auction config/trusted scoring signals url=]'s [=url/origin=] is not
+ [=same origin=] with |auctionConfig|'s [=auction config/seller=], then set |isCrossOrigin| to
+ true.
+ 1. Let |result| be the result of [=fetching trusted scoring signals with batching=] with
+ |batcher| and |request|.
+ 1. If |result| is not failure:
+ 1. Let |allTrustedScoringSignals| be |result|'s [=trusted scoring signals reply/all trusted
+ scoring signals=]:
+ 1. Set |scoringDataVersion| to |result|'s [=trusted scoring signals reply/data version=].
1. Let |trustedScoringSignals| be a new empty [=map=].
1. [=map/Set=] |trustedScoringSignals|["`renderURL`"] to a new empty [=map=].
1. If |allTrustedScoringSignals|["`renderURLs`"] [=map/exists=] and
@@ -2093,31 +2091,35 @@ a [=generated bid=] |generatedBid|, a [=script fetcher=] |decisionLogicFetcher|,
[=map/exists=], then [=map/set=] |adComponentRenderURLsValue|[|adComponentRenderURL|] to
|allTrustedScoringSignals|["`adComponentRenderURLs`"][|adComponentRenderURL|].
1. [=map/Set=] |trustedScoringSignals|["`adComponentRenderURLs`"] to |adComponentRenderURLsValue|.
- 1. If |crossOriginTrustedScoringSignalsOrigin| is null, set |sameOriginTrustedScoringSignals|
+ 1. If |isCrossOrigin| is false, set |sameOriginTrustedScoringSignals|
to |trustedScoringSignals|.
1. Otherwise:
1. Set |crossOriginTrustedScoringSignals| to a new [=map=].
1. Let |originKey| be the [=serialization of an origin|serialization=] given
- |crossOriginTrustedScoringSignalsOrigin|.
+ |auctionConfig|'s [=auction config/trusted scoring signals url=]'s [=url/origin=].
1. [=map/Set=] |crossOriginTrustedScoringSignals|[|originKey|] to |trustedScoringSignals|.
-1. Return «|crossOriginTrustedScoringSignalsOrigin|, |sameOriginTrustedScoringSignals|,
- |crossOriginTrustedScoringSignals|, |scoringDataVersion|»
+ 1. Otherwise if |auctionConfig|'s [=auction config/seller real time reporting config=]
+ is "`default-local-reporting`",then:
+ 1. [=Add a platform contribution=] with [=trusted scoring signals failure bucket=],
+ |realTimeContributionsMap|, and |auctionConfig|'s [=auction config/seller=].
+1. Return «|isCrossOrigin|, |sameOriginTrustedScoringSignals|, |crossOriginTrustedScoringSignals|,
+ |scoringDataVersion|»
To score and rank a bid given an [=auction config=] |auctionConfig|, a [=generated bid=]
|generatedBid|, a [=bid debug reporting info=] |bidDebugReportInfo|, a [=leading bid info=] |leadingBidInfo|,
-a [=script fetcher=] |decisionLogicFetcher|, a {{DirectFromSellerSignalsForSeller}}
-|directFromSellerSignalsForSeller|, an {{unsigned long}}-or-null |biddingDataVersion|, an enum |auctionLevel|,
-which is "single-level-auction", "top-level-auction", or "component-auction", a [=currency tag=]
-|componentAuctionExpectedCurrency|, an [=origin=] |topLevelOrigin|, and a
-[=real time reporting contributions map=] |realTimeContributionsMap|:
+a [=script fetcher=] |decisionLogicFetcher|, a [=trusted scoring signals batcher=] |trustedScoringSignalsBatcher|
+a {{DirectFromSellerSignalsForSeller}} |directFromSellerSignalsForSeller|, an {{unsigned long}}-or-null
+|biddingDataVersion|, an enum |auctionLevel|, which is "single-level-auction", "top-level-auction",
+or "component-auction", a [=currency tag=] |componentAuctionExpectedCurrency|, an [=origin=]
+|topLevelOrigin|, and a [=real time reporting contributions map=] |realTimeContributionsMap|:
-1. Let «|crossOriginTrustedScoringSignalsOrigin|, |sameOriginTrustedScoringSignals|,
+1. Let «|trustedScoringSignalsAreCrossOrigin|, |sameOriginTrustedScoringSignals|,
|crossOriginTrustedScoringSignals|, |scoringDataVersion|» be the result of [=fetch and
- decode trusted scoring signals=] given |auctionConfig|, |generatedBid|, |decisionLogicFetcher|,
- |topLevelOrigin|, and |realTimeContributionsMap|.
+ decode trusted scoring signals=] given |trustedScoringSignalsBatcher|, |auctionConfig|,
+ |generatedBid|, |decisionLogicFetcher|, |topLevelOrigin|, and |realTimeContributionsMap|.
1. Let |adMetadata| be |generatedBid|'s [=generated bid/ad=].
1. Let |bidValue| be |generatedBid|'s [=generated bid/bid=].
1. If |generatedBid|'s [=generated bid/modified bid=] is not null, then set |bidValue| to
@@ -2141,11 +2143,11 @@ which is "single-level-auction", "top-level-auction", or "component-auction", a
The result of [=serializing a currency tag=] with |generatedBid|'s [=generated bid/bid=]'s
[=bid with currency/currency=]
{{ScoringBrowserSignals/dataVersion}}
- |scoringDataVersion| if it is not null and |crossOriginTrustedScoringSignalsOrigin| is null,
+ |scoringDataVersion| if it is not null and |trustedScoringSignalsAreCrossOrigin| is false,
unset otherwise.
{{ScoringBrowserSignals/crossOriginDataVersion}}
- |scoringDataVersion| if it is not null and |crossOriginTrustedScoringSignalsOrigin| is not
- null, unset otherwise.
+ |scoringDataVersion| if it is not null and |trustedScoringSignalsAreCrossOrigin| is true,
+ unset otherwise.
{{ScoringBrowserSignals/adComponents}}
|generatedBid|'s [=generated bid/ad component descriptors=] [=converted to a string sequence=]
{{ScoringBrowserSignals/forDebuggingOnlyInCooldownOrLockout}}
@@ -2516,71 +2518,6 @@ To calculate the ad slot size query param given an [=interest group=]
-
-
-To build trusted bidding signals url given a [=URL=] |signalsUrl|, an [=ordered set=] of
-[=strings=] |keys|, an [=ordered set=] of [=strings=] |igNames|, an {{unsigned short}}-or-null
-|experimentGroupId|, an [=origin=] |topLevelOrigin|, and a [=string=] |slotSizeQueryParam|:
-1. Let |queryParamsList| be a new empty [=list=].
-
- Note: These steps create a [=url/query=] of the form "`&=`".
- E.g., "`hostname=publisher1.com&keys=key1,key2&interestGroupNames=ad+platform,name2&experimentGroupId=1234`".
-
These steps don't use the [=urlencoded serializer|application/x-www-form-urlencoded
- serializer=] to construct the query string because it repeats a key if it has multiple values
- instead of a comma-demilited list (e.g., "`keys=key1&keys=key2`", instead of
- "`keys=key1,key2`"), and it also uses a different percent encode set from the Chrome
- implementation.
-
-1. [=list/Append=] "hostname=" to |queryParamsList|.
-1. [=list/Append=] the result of [=string/UTF-8 percent-encoding=] the
- [=serialization of an origin|serialized=] |topLevelOrigin| using [=component percent-encode set=]
- to |queryParamsList|.
-1. If |keys| is not [=set/is empty|empty=]:
- 1. [=list/Append=] "`&keys=`" to |queryParamsList|.
- 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
- |keys|.
-1. If |igNames| is not [=set/is empty|empty=]:
- 1. [=list/Append=] "`&interestGroupNames=`" to |queryParamsList|.
- 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
- |igNames|.
-1. If |experimentGroupId| is not null:
- 1. [=list/Append=] "`&experimentGroupId=`" to |queryParamsList|.
- 1. [=list/Append=] [=serialize an integer|serialized=] |experimentGroupId| to |queryParamsList|.
-1. [=list/Append=] |slotSizeQueryParam| to |queryParamsList|.
-1. Let |fullSignalsUrl| be |signalsUrl|.
-1. Set |fullSignalsUrl|'s [=url/query=] to the result of [=string/concatenating=] |queryParamsList|.
-1. return |fullSignalsUrl|.
-
-
-
-
-
-To build trusted scoring signals url given a [=URL=] |signalsUrl|, a [=list=] of
-[=strings=] |renderURLs|, an [=ordered set=] of [=strings=] |adComponentRenderURLs|, an
-{{unsigned short}} |experimentGroupId|, and an [=origin=] |topLevelOrigin|:
-
-Note: When trusted scoring signals fetches are not batched, |renderURLs|'s [=list/size=] is 1.
-
-1. Let |queryParamsList| be a new empty [=list=].
-1. [=list/Append=] "hostname=" to |queryParamsList|.
-1. [=list/Append=] the result of [=string/UTF-8 percent-encoding=] |topLevelOrigin| using
- [=component percent-encode set=] to |queryParamsList|.
-1. If |renderURLs| is not [=set/is empty|empty=]:
- 1. [=list/Append=] "`&renderURLs=`" to |queryParamsList|.
- 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
- |renderURLs|.
-1. If |adComponentRenderURLs| is not [=set/is empty|empty=]:
- 1. [=list/Append=] "`&adComponentRenderURLs=`" to |queryParamsList|.
- 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
- |adComponentRenderURLs|.
-1. If |experimentGroupId| is not null:
- 1. [=list/Append=] "`&experimentGroupId=`" to |queryParamsList|.
- 1. [=list/Append=] [=serialize an integer|serialized=] |experimentGroupId| to |queryParamsList|.
-1. Set |signalsUrl|'s [=url/query=] to the result of [=string/concatenating=] |queryParamsList|.
-1. return |signalsUrl|.
-
-
-
To send report given a [=URL=] |url|, and an [=environment settings object=] |settings|:
@@ -6562,6 +6499,42 @@ To append to a bidding signals per-interest group data map given an [
+
+
+To build trusted bidding signals url given a [=URL=] |signalsUrl|, an [=ordered set=] of
+[=strings=] |keys|, an [=ordered set=] of [=strings=] |igNames|, an {{unsigned short}}-or-null
+|experimentGroupId|, an [=origin=] |topLevelOrigin|, and a [=string=] |slotSizeQueryParam|:
+1. Let |queryParamsList| be a new empty [=list=].
+
+ Note: These steps create a [=url/query=] of the form "`&=`".
+ E.g., "`hostname=publisher1.com&keys=key1,key2&interestGroupNames=ad+platform,name2&experimentGroupId=1234`".
+
These steps don't use the [=urlencoded serializer|application/x-www-form-urlencoded
+ serializer=] to construct the query string because it repeats a key if it has multiple values
+ instead of a comma-demilited list (e.g., "`keys=key1&keys=key2`", instead of
+ "`keys=key1,key2`"), and it also uses a different percent encode set from the Chrome
+ implementation.
+
+1. [=list/Append=] "hostname=" to |queryParamsList|.
+1. [=list/Append=] the result of [=string/UTF-8 percent-encoding=] the
+ [=serialization of an origin|serialized=] |topLevelOrigin| using [=component percent-encode set=]
+ to |queryParamsList|.
+1. If |keys| is not [=set/is empty|empty=]:
+ 1. [=list/Append=] "`&keys=`" to |queryParamsList|.
+ 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
+ |keys|.
+1. If |igNames| is not [=set/is empty|empty=]:
+ 1. [=list/Append=] "`&interestGroupNames=`" to |queryParamsList|.
+ 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
+ |igNames|.
+1. If |experimentGroupId| is not null:
+ 1. [=list/Append=] "`&experimentGroupId=`" to |queryParamsList|.
+ 1. [=list/Append=] [=serialize an integer|serialized=] |experimentGroupId| to |queryParamsList|.
+1. [=list/Append=] |slotSizeQueryParam| to |queryParamsList|.
+1. Let |fullSignalsUrl| be |signalsUrl|.
+1. Set |fullSignalsUrl|'s [=url/query=] to the result of [=string/concatenating=] |queryParamsList|.
+1. Return |fullSignalsUrl|.
+
+
To fetch the current outstanding trusted signals batch given a
@@ -6652,6 +6625,226 @@ To batch or fetch trusted bidding signals given a [=trusted bidding s
+Trusted scoring signals batcher
+
+A trusted scoring signals batcher helps manage merging multiple trusted scoring signals
+requests into smaller number of fetches. It's a [=struct=] with the following [=struct/items=]:
+
+
+ : request queue
+ :: A [=list=] of [=trusted scoring signals requests=] that hasn't yet been organized to aid
+ batching.
+ : request map
+ :: A [=map=] from a tuple of [=script fetcher=], a [=URL=] representating the trusted signals
+ base [=URL=], {{unsigned short}} or null for experiment ID, and
+ [=origin=], representing the top frame's [=origin], to a [=list=] of [=trusted scoring signals
+ requests=]. This organizes fetches that can possibly be merged together.
+ : url length limit
+ :: A {{long}} denoting a user-configured limit which should not be exceeded due to combining of
+ fetches. 0 denotes no limit, and is the initial value.
+
+
+A trusted scoring signals request is a [=struct=] with the following [=struct/items=],
+representing all information needed to produce a trusted scoring signals fetch for a single scoring
+invocation:
+
+
+ : seller
+ :: An [=origin=] of the seller the fetch is on behalf of.
+ : seller script fetcher.
+ :: A [=script fetcher=] for the seller's decision logic script.
+ : base url
+ :: A [=URL=], the base URL for trusted seller signals to fetch.
+ : seller experiment group id
+ :: Null or an {{unsigned short}}, initially null.
+ : top level origin
+ :: An [=origin=]. The origin of top-level frame in the hierarchy containing the document running
+ the auction.
+ : render URL
+ :: A [=string=], the serialized main URL of the creative to pass in the fetch.
+ : ad component URLs
+ :: A [=set=] of [=strings=], list of serialized component URLs of the creative to pass in the
+ fetch.
+ : policy container
+ :: A [=policy container=] to use for the network fetch.
+ : reply
+ :: A [=trusted scoring signals reply=], null, or failure. Initially null. Set to a non-null value
+ when the fetch has been completed.
+
+
+A trusted scoring signals reply is a [=struct=] with the following [=struct/items=]
+
+ : all trusted scoring signals
+ :: A [=ordered map=] or failure.
+ : data version
+ :: An {{unsigned long}} or null.
+
+
+
+
+To create a trusted scoring signals batcher given a {{long}} |urlLengthLimit|:
+
+1. Let |batcher| be a new [=trusted scoring signals batcher=].
+1. Set |batcher|'s [=trusted scoring signals batcher/url length limit=] to |urlLengthLimit|.
+1. Let |queue| be the result of [=starting a new parallel queue=].
+1. [=parallel queue/enqueue steps|Enqueue the following steps=] to |queue|:
+ 1. [=Batch and fetch trusted scoring signals=] given |batcher|.
+1. Return |batcher|.
+
+
+
+
+
+To fetch trusted scoring signals with batching given a [=trusted scoring signals
+batcher=] |batcher| and a [=trusted scoring signals request=] |request|:
+1. [=list/Append=] |request| to |batcher|'s [=trusted scoring signals batcher/request queue=].
+1. Wait until |request|'s [=trusted scoring signals request/reply=] is non-null.
+1. Return |request|'s [=trusted scoring signals request/reply=].
+
+
+
+
+
+To build trusted scoring signals url given a [=URL=] |signalsUrl|, a [=list=] of
+[=strings=] |renderURLs|, an [=ordered set=] of [=strings=] |adComponentRenderURLs|, an
+{{unsigned short}} |experimentGroupId|, and an [=origin=] |topLevelOrigin|:
+
+Note: When trusted scoring signals fetches are not batched, |renderURLs|'s [=list/size=] is 1.
+
+1. Let |queryParamsList| be a new empty [=list=].
+1. [=list/Append=] "hostname=" to |queryParamsList|.
+1. [=list/Append=] the result of [=string/UTF-8 percent-encoding=] |topLevelOrigin| using
+ [=component percent-encode set=] to |queryParamsList|.
+1. If |renderURLs| is not [=set/is empty|empty=]:
+ 1. [=list/Append=] "`&renderURLs=`" to |queryParamsList|.
+ 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
+ |renderURLs|.
+1. If |adComponentRenderURLs| is not [=set/is empty|empty=]:
+ 1. [=list/Append=] "`&adComponentRenderURLs=`" to |queryParamsList|.
+ 1. [=list/Extend=] |queryParamsList| with the result of [=encode trusted signals keys=] with
+ |adComponentRenderURLs|.
+1. If |experimentGroupId| is not null:
+ 1. [=list/Append=] "`&experimentGroupId=`" to |queryParamsList|.
+ 1. [=list/Append=] [=serialize an integer|serialized=] |experimentGroupId| to |queryParamsList|.
+1. Set |signalsUrl|'s [=url/query=] to the result of [=string/concatenating=] |queryParamsList|.
+1. Return |signalsUrl|.
+
+
+
+
+To build batched trusted scoring signals url given a non-empty [=list=] of [=trusted
+scoring signals requests=] |entriesToBatch|:
+
+1. Let |firstEntry| be |entriesToBatch|[0].
+1. Let |renderURLs| be an empty [=ordered set=] of [=strings=].
+1. Let |adComponentRenderURLs| be an empty [=ordered set=] of [=strings=]
+ |adComponentRenderURLs|
+1. [=list/For each=] |entry| of |entriesToBatch|:
+ 1. [=Assert=] that |entry|'s [=trusted scoring signals request/base URL=] is equal to
+ |firstEntry|'s [=trusted scoring signals request/base URL=].
+ 1. [=Assert=] that |entry|'s [=trusted scoring signals request/seller experiment group id=] is
+ equal to |firstEntry|'s [=trusted scoring signals request/seller experiment group id=].
+ 1. [=Assert=] that |entry|'s [=trusted scoring signals request/top level origin=] is equal to
+ |firstEntry|'s [=trusted scoring signals request/top level origin=].
+ 1. [=Assert=] that |entry|'s [=trusted scoring signals request/seller script fetcher=] is equal to
+ |firstEntry|'s [=trusted scoring signals request/seller script fetcher=].
+ 1. [=Assert=] that |entry|'s [=trusted scoring signals request/policy container=] is equal to
+ |firstEntry|'s [=trusted scoring signals request/policy container=].
+ 1. [=set/Append=] |entry|'s [=trusted scoring signals request/render URL=] to |renderURLs|.
+ 1. [=list/Extend=] |adComponentRenderURLs| with |entry|'s [=trusted scoring signals request/
+ ad component URLs=].
+1. Return the result of [=building trusted scoring signals url=] with |firstEntry|'s [=trusted
+ scoring signals request/base URL=], |renderURLs|, |adComponentRenderURLs|, |firstEntry|'s
+ [=trusted scoring signals request/seller experiment group id=],
+ |firstEntry|'s [=trusted scoring signals request/top level origin=].
+
+
+
+
+To check if trusted scoring signals batch honors URL length limit given a
+[=trusted scoring signals batcher=] |batcher| and a non-empty [=list=] of [=trusted
+scoring signals requests=] |entriesToBatch|:
+
+1. If the [=list/size=] of |entriesToBatch| is 1, return true.
+1. If |batcher|'s [=trusted scoring signals batcher/url length limit=] is 0, return true.
+1. Return whether the [=string/length=] of the result of [=building batched trusted scoring signals
+ url=] for |entriesToBatch| ≤ |batcher|'s [=trusted scoring signals batcher/url length
+ limit=].
+
+
+
+
+
+To batch and fetch trusted scoring signals given a [=trusted scoring signals batcher=]
+|batcher|:
+
+1. [=Assert=] that these steps are running [=in parallel=].
+1. Until |batcher| is no longer needed:
+ 1. Wait until at least one of the following is true:
+ * |batcher|'s [=trusted scoring signals batcher/request queue=] [=list/is not empty=].
+ * |batcher|'s [=trusted scoring signals batcher/request map=] [=map/is not empty=] and some
+ heuristically chosen amount of time has passed.
+ 1. Atomically do:
+ 1. Let |incomingRequests| be a [=list/clone=] of |batcher|'s [=trusted scoring signals batcher/
+ request queue=].
+ 1. [=list/Empty=] |batcher|'s [=trusted scoring signals batcher/request queue=].
+
+ Note: the result of atomicity is that any concurrent attempts to modify |batcher|'s [=trusted
+ scoring signals batcher/request queue=] while these steps are running will not result in
+ different items being removed by the [=list/Empty=] operation than were cloned into
+ |incomingRequests|.
+
+ 1. [=list/For each=] |request| in |incomingRequests|:
+ 1. Let |key| be (|request|'s [=trusted scoring signals request/seller script fetcher=],
+ |request|'s [=trusted scoring signals request/base url=], |request|'s [=trusted scoring
+ signals request/seller experiment group id=], |request|'s [=trusted scoring signals request/
+ top level origin=]).
+ 1. If |batcher|'s [=trusted scoring signals batcher/request map=][|key|] does not [=map/exist=],
+ then [=map/set=] |batcher|'s [=trusted scoring signals batcher/request map=][|key|] to an
+ [=list/is empty|empty=] [=list=].
+ 1. [=list/Append=] |request| to |batcher|'s [=trusted scoring signals batcher/request
+ map=][|key|].
+ 1. Some number of times, heuristically, select a |key| and a non-[=list/is empty|empty=] [=set/
+ subset=] of |batcher|'s [=trusted scoring signals batcher/request map=][|key|], called
+ |entriesToBatch|, such that [=checking if trusted scoring signals batch honors URL length
+ limit=] on |batcher| and |entriesToBatch| returns true:
+
+ Note: implementations are free to wait to collect more requests to merge (by leaving things
+ in the |batcher|'s [=trusted scoring signals batcher/request map=]), or send them
+ individually, but need to take into account the configured URL length limit if they do combine
+ requests. All entries need to be handled eventually.
+
+ 1. [=list/Remove=] |entriesToBatch| from |batcher|'s [=trusted scoring signals batcher/
+ request map=][|key|].
+ 1. If |batcher|'s [=trusted scoring signals batcher/request map=][|key|] [=list/is empty=],
+ then [=map/remove=] |key| from |batcher|'s [=trusted scoring signals batcher/request map=].
+ 1. Let |fullSignalsUrl| be the result of [=building batched trusted scoring signals url=] for
+ |entriesToBatch|.
+ 1. Let |seller| be |entriesToBatch|[0]'s [=trusted scoring signals request/seller=].
+ 1. Let |scriptFetcher| be |entriesToBatch|[0]'s [=trusted scoring signals request/seller
+ script fetcher=].
+ 1. Let |policyContainer| be |entriesToBatch|[0]'s [=trusted scoring signals request/policy
+ container=].
+ 1. If |fullSignalsUrl|'s [=url/origin=] is not [=same origin=] with |seller| then:
+ 1. Let |allowCrossOriginTrustedScoringSignalsFrom| be the result of [=wait for cross origin
+ trusted scoring signals authorization from a fetcher=] given |scriptFetcher|.
+ 1. If |allowCrossOriginTrustedScoringSignalsFrom| does not [=list/contain=]
+ |fullSignalsUrl|'s [=url/origin=], set |fullSignalsUrl| to null.
+ 1. Let |result| be failure.
+ 1. If |fullSignalsUrl| is not null:
+ 1. Let «|allTrustedScoringSignals|, ignored, |scoringDataVersion|» be
+ the result of [=fetching trusted signals=] with |fullSignalsUrl|, |seller|,
+ |policyContainer|, and false.
+ 1. If |allTrustedScoringSignals| is an [=ordered map=]:
+ 1. Set |result| to a new [=trusted scoring signals reply=]
+ 1. Set |result|'s [=trusted scoring signals reply/all trusted scoring signals=] to
+ |allTrustedScoringSignals|.
+ 1. Set |result|'s [=trusted scoring signals reply/data version=] to |scoringDataVersion|.
+ 1. [=list/For each=] |entry| in |entriesToBatch|:
+ 1. Set |entry|'s [=trusted scoring signals request/reply=] to |result|.
+
+
+
A generated bid is a bid that needs to be scored by the seller. The bid is either the