Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spec: macro reporting support #762

Merged
merged 10 commits into from
Sep 12, 2023
116 changes: 88 additions & 28 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@ partial interface Navigator {
dictionary AuctionAd {
required USVString renderURL;
any metadata;

USVString buyerReportingId;
USVString buyerAndSellerReportingId;
sequence<USVString> allowedReportingOrigins;
};

dictionary GenerateBidInterestGroup {
Expand Down Expand Up @@ -278,6 +280,16 @@ This is detectable because it can change the set of fields that are read from th
|igAd|'s [=interest group ad/buyer reporting ID=] to it.
1. If |ad|["{{AuctionAd/buyerAndSellerReportingId}}"] [=map/exists=],
then set |igAd|'s [=interest group ad/buyer and seller reporting ID=] to it.
1. If |ad|["{{AuctionAd/allowedReportingOrigins}}"] [=map/exists=]:
1. Let |allowedReportingOrigins| be a new [=list=] of [=origins=].
1. [=list/For each=] |originStr| in |ad|["{{AuctionAd/allowedReportingOrigins}}"]:
1. Let |origin| be the result of [=parsing an origin=] on |originStr|.
1. If |origin| is failure, or its [=url/scheme=] is not "`https`", [=exception/throw=] a
{{TypeError}}.
1. [=list/Append=] |origin| to |allowedReportingOrigins|.
1. If [=list/size=] of |allowedReportingOrigins| is greater than 10, [=exception/throw=]
a {{TypeError}}.
1. Set |igAd|'s [=interest group ad/allowed reporting origins=] to |allowedReportingOrigins|.
1. [=list/Append=] |igAd| to |interestGroup|'s |interestGroupField|.
1. If |interestGroup|'s [=interest group/estimated size=] is greater than 50 KB, then
[=exception/throw=] a {{TypeError}}.
Expand Down Expand Up @@ -322,7 +334,6 @@ The <dfn for="interest group">estimated size</dfn> of an [=interest group=] |ig|
[=interest group/priority signals overrides=]:
1. The [=string/length=] of |key|.
1. 8 bytes, which is the size of |value|.
1. The size of [=interest group/execution mode=].
1. The [=string/length=] of the [=URL serializer|serialization=] of |ig|'s
[=interest group/bidding url=], if the field is not null.
1. The [=string/length=] of the [=URL serializer|serialization=] of |ig|'s
Expand All @@ -339,7 +350,11 @@ The <dfn for="interest group">estimated size</dfn> of an [=interest group=] |ig|
[=interest group ad/render url=].
1. The [=string/length=] of |ad|'s [=interest group ad/metadata=] if the field is not null.
1. The [=string/length=] of |ad|'s [=interest group ad/buyer reporting ID=] if the field is not null.
1. The [=string/length=] of |ad|'s [=interest group ad/buyer and seller reporting ID=] if the field is not null.
1. The [=string/length=] of |ad|'s [=interest group ad/buyer and seller reporting ID=] if the
field is not null.
1. If |ad|'s [=interest group ad/allowed reporting origins=] is not null, [=list/for each=]
|origin| of it:
1. The [=string/length=] of the [=serialization of an origin|serialization=] of |origin|.
1. If |ig|'s [=interest group/ad components=] is not null, [=list/for each=] |ad| of it:
1. The [=string/length=] of the [=URL serializer|serialization=] of |ad|'s
[=interest group ad/render url=].
Expand Down Expand Up @@ -723,14 +738,22 @@ To <dfn>asynchronously finish reporting</dfn> given a
1. [=iteration/While=]:
1. If |buyerDone|, |sellerDone|, and |componentSellerDone| are all true, then
[=iteration/break=].
1. Wait until |leadingBidInfo|'s [=leading bid info/buyer reporting result=] is not null,
or |leadingBidInfo|'s [=leading bid info/seller reporting result=] is not null, or
|leadingBidInfo|'s [=leading bid info/component seller reporting result=] is not null.
1. Wait until one of the following fields of |leadingBidInfo| being not null:
* [=leading bid info/buyer reporting result=];
* [=leading bid info/seller reporting result=];
* [=leading bid info/component seller reporting result=].
1. If |buyerDone| is false and |leadingBidInfo|'s [=leading bid info/buyer reporting result=]
is not null:
1. Let |buyerMap| be |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s
[=reporting result/reporting beacon map=].
1. If |buyerMap| is null, set |buyerMap| to an empty [=map=] 芦[]禄.
1. Let |allowedReportingOrigins| be |leadingBidInfo|'s [=leading bid info/leading bid=]'s
[=generated bid/bid ad=]'s [=interest group ad/allowed reporting origins=].
1. Let |macroMap| be |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s
[=reporting result/reporting macro map=].
1. TODO: Pass |macroMap| and |allowedReportingOrigins| to [=Finalize a reporting destination=]
when it is updated to take the parameters. May need to convert |macroMap| to a list, based
on what that function expects.
1. [=Finalize a reporting destination=] with |reportingMap|,
{{FenceReportingDestination/buyer}}, and |buyerMap|.
1. [=Send report=] to |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s
Expand Down Expand Up @@ -1260,9 +1283,9 @@ To <dfn>generate and score bids</dfn> given an [=auction config=] |auctionConfig
1. If |originalAds| is not null:
1. Set |ig|'s [=interest group/ads=] to a new [=list=] of [=interest group ad=].
1. [=list/For each=] |ad| in |originalAds|:
1. If [=query ad k-anonymity count=] given |ig| and |ad|'s
[=interest group ad/render url=] returns true, [=list/append=] |ad| to |ig|'s
[=interest group/ads=].
1. If [=query ad k-anonymity count=] given |ig| and |ad|'s
[=interest group ad/render url=] returns true, [=list/append=] |ad| to |ig|'s
[=interest group/ads=].
1. Let |originalAdComponents| be |ig|'s [=interest group/ad components=].
1. If |originalAdComponents| is not null:
1. Set |ig|'s [=interest group/ad components=] to a new [=list=] of [=interest group ad=].
Expand Down Expand Up @@ -1863,7 +1886,7 @@ null |winningComponentConfig|:
1. [=map/Set=] |browserSignals|["{{ReportingBrowserSignals/buyerAndSellerReportingId}}"] to |igAd|'s [=interest group ad/buyer and seller reporting ID=].
1. Let |sellerReportingScript| be the result of [=fetching script=] with |config|'s
[=auction config/decision logic url=].
1. Let 芦 |sellerSignals|, |reportUrl|, |reportingBeaconMap| 禄 be the result of
1. Let 芦 |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored 禄 be the result of
[=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`", and
芦 |config|'s [=auction config/config idl=], |browserSignals| 禄.
1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]:
Expand Down Expand Up @@ -1928,8 +1951,8 @@ and a {{ReportingBrowserSignals}} |browserSignals|:
1. Otherwise, [=map/Set=] |reportWinBrowserSignals|["{{ReportWinBrowserSignals/interestGroupName}}"] to |winner|'s [=generated bid/interest group=] [=interest group/name=].
1. Let |buyerReportingScript| be the result of [=fetching script=] with |winner|'s
[=generated bid/interest group=]'s [=interest group/bidding url=].
1. Let 芦 ignored, |resultUrl|, |reportingBeaconMap| 禄 be the result of [=evaluating a
reporting script=] with |buyerReportingScript|, "`reportWin`", and
1. Let 芦 ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap| 禄 be the result of
[=evaluating a reporting script=] with |buyerReportingScript|, "`reportWin`", and
芦 |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config idl=]'s
{{AuctionAdConfig/auctionSignals}}, |perBuyerSignalsForBuyer|, |sellerSignals|,
|reportWinBrowserSignals| 禄.
Expand All @@ -1940,6 +1963,9 @@ and a {{ReportingBrowserSignals}} |browserSignals|:

: [=reporting result/reporting beacon map=]
:: |reportingBeaconMap|

: [=reporting result/reporting macro map=]
:: |reportingMacroMap|
</div>

# K-anonymity # {#k-anonymity}
Expand Down Expand Up @@ -2275,8 +2301,10 @@ of the following global objects:
exception was [=exception/thrown=] in the previous step, keep |resultJSON| as "null".
1. Let |reportURL| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/report url=]
1. If |reportURL| is failure, set |reportURL| to null.
1. Let |macroMap| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=]
if |functionName| is "`reportWin`", null otherwise.
1. Return 芦 |resultJSON|, |reportURL|,
|global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=] 禄.
|global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=], |macroMap| 禄.
</div>

<div algorithm>
Expand Down Expand Up @@ -2429,13 +2457,15 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
1. Let |adUrl| be the result of running the [=URL parser=] on
|generateBidOutput|["{{GenerateBidOutput/render}}"].
1. If |adUrl| is failure, return failure.
1. If [=validating an ad url=] given |adUrl|, |ig|, and false returns false, return failure.
1. Set |adDescriptor|'s [=ad descriptor/url=] to |adUrl|.
1. Otherwise:
1. Set |adDescriptor| to the result of [=converting an ad render=] given
|generateBidOutput|["{{GenerateBidOutput/render}}"], |ig| and false.
|generateBidOutput|["{{GenerateBidOutput/render}}"].
1. If |adDescriptor| is failure, return failure.
1. Let |bidAd| be the result of [=finding matching ad=] given |adDescriptor|, |ig|, and false.
1. If |bidAd| is null, return failure.
1. Set |bid|'s [=generated bid/ad descriptor=] to |adDescriptor|.
1. Set |bid|'s [=generated bid/bid ad=] to |bidAd|.
1. If |generateBidOutput|["{{GenerateBidOutput/adComponents}}"] [=map/exists=]:
1. Let |adComponents| be |generateBidOutput|["{{GenerateBidOutput/adComponents}}"].
1. Return failure if any of the following conditions hold:
Expand All @@ -2447,12 +2477,11 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
1. If |component| is {{DOMString}}:
1. Let |componentUrl| be the result of running the [=URL parser=] on |component|.
1. If |componentUrl| is failure, return failure.
1. If [=validating an ad url=] given |componentUrl|, |ig|, and true returns false, return failure.
1. Set |componentDescriptor|'s [=ad descriptor/url=] to |componentUrl|.
1. Otherwise:
1. Set |componentDescriptor| to the result of [=converting an ad render=] given |component|, |ig|,
and true.
1. Set |componentDescriptor| to the result of [=converting an ad render=] given |component|.
1. If |componentDescriptor| is failure, return failure.
1. If [=finding matching ad=] given |componentUrl|, |ig|, and true returns null, return failure.
1. [=list/Append=] |componentDescriptor| to |adComponentDescriptors|.
1. Set |bid|'s [=generated bid/ad component descriptors=] to |adComponentDescriptors|.
1. If |generateBidOutput|["{{GenerateBidOutput/adCost}}"] [=map/exists=]:
Expand Down Expand Up @@ -2486,12 +2515,10 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
</div>

<div algorithm>
To <dfn>convert an ad render</dfn> given an {{AdRender}} |adRender|, an [=interest group=] |ig|,
and a [=boolean=] |isComponent|:
To <dfn>convert an ad render</dfn> given an {{AdRender}} |adRender|:

1. Let |adUrl| be the result of running the [=URL parser=] on |adRender|["{{AdRender/url}}"].
1. If |adUrl| is failure, return failure.
1. If [=validating an ad url=] given |adUrl|, |ig|, and |isComponent| returns false, return failure.
1. Let |adDescriptor| be a new [=ad descriptor=].
1. Set |adDescriptor|'s [=ad descriptor/url=] to |adUrl|.
1. If |adRender|["{{AdRender/width}}"] [=map/exists=]:
Expand All @@ -2510,17 +2537,19 @@ To <dfn>convert GenerateBidOutput to generated bid</dfn> given a {{GenerateBidOu
</div>

<div algorithm>
To <dfn>validate an ad url</dfn> given a [=URL=] |adUrl|, an [=interest group=] |ig|, and a
[=boolean=] |isComponent|:
To <dfn>find matching ad</dfn> given an [=ad descriptor=] |adDescriptor|, an [=interest group=]
|ig|, and a [=boolean=] |isComponent|:

1. If |adUrl|'s [=url/scheme=] is not "`https`", return false.
1. Let |adUrl| be |adDescriptor|'s [=ad descriptor/url=].
1. If |adUrl|'s [=url/scheme=] is not "`https`", return null.
1. TODO: Need to check [=ad descriptor/size=] as well.
1. If |isComponent|:
1. [=list/For each=] |ad| in |ig|'s [=interest group/ad components=]:
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return true.
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return |ad|.
1. Otherwise:
1. [=list/For each=] |ad| in |ig|'s [=interest group/ads=]:
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return true.
1. Return false.
1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return |ad|.
1. Return null.
</div>

<div algorithm>
Expand Down Expand Up @@ -2586,17 +2615,24 @@ interface InterestGroupReportingScriptRunnerGlobalScope
: InterestGroupScriptRunnerGlobalScope {
undefined sendReportTo(DOMString url);
undefined registerAdBeacon(record&lt;DOMString, USVString&gt; map);
undefined registerAdMacro(DOMString name, USVString value);
};

</pre>

Note: {{InterestGroupReportingScriptRunnerGlobalScope/registerAdMacro(name, value)}} is only
available in [=report win=], but not [=report result=].

Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a
<dl dfn-for="InterestGroupReportingScriptRunnerGlobalScope">
: <dfn>report url</dfn>
:: Null, failure, or a [=URL=]. Defaulting to null.
: <dfn>reporting beacon map</dfn>
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=URLs=]. Defaulting to null.
: <dfn>reporting macro map</dfn>
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=strings=]. Defaulting to null.

</dl>

Expand Down Expand Up @@ -2642,6 +2678,13 @@ Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a
reporting beacon map=] to |map|.
</div>

<div algorithm>
The <dfn method for="InterestGroupReportingScriptRunnerGlobalScope">registerAdMacro(|name|,
|value|)</dfn> method steps are:

1. [=map/Set=] [=this=]'s [=relevant global object=]'s
[=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=][|name|] to |value|.
</div>

# Interest Group Updates # {#interest-group-updates}

Expand Down Expand Up @@ -3105,9 +3148,19 @@ An interest group ad is a [=struct=] with the following [=struct/items=]:
: <dfn>metadata</dfn>
:: Null or a [=string=]. Extra arbitary information about this ad, passed to `generateBid()`.
: <dfn>buyer reporting ID</dfn>
:: Null or a [=string=]. Will be passed in place of interest group name to `reportWin()`, subject to k-anonymity checks.
:: Null or a [=string=]. Will be passed in place of interest group name to [=report win=], subject
to k-anonymity checks. Only meaningful in [=interest group/ads=], but ignored in
[=interest group/ad components=].
: <dfn>buyer and seller reporting ID</dfn>
:: Null or a [=string=]. Will be passed in place of interest group name or [=interest group ad/buyer reporting ID=] to `reportWin()` and `reportResult()`, subject to k-anonymity checks.
:: Null or a [=string=]. Will be passed in place of interest group name or
[=interest group ad/buyer reporting ID=] to [=report win=] and [=report result=], subject to
k-anonymity checks. Only meaningful in [=interest group/ads=], but ignored in
[=interest group/ad components=].
: <dfn>allowed reporting origins</dfn>
:: Null or a [=list=] of [=origins=]. A list of up to 10 reporting origins that can receive reports
with registered macros. All origins must be HTTPS origins and
<a href="https://github.com/privacysandbox/attestation">enrolled</a>. Only meaningful in
[=interest group/ads=], but ignored in [=interest group/ad components=].

</dl>

Expand Down Expand Up @@ -3368,6 +3421,8 @@ the seller.
:: Null or an {{unsigned short}}. A 0-4095 integer (12-bits) passed to `reportWin()`, with noising.
: <dfn>interest group</dfn>
:: An [=interest group=], whose `generateBid()` invocation generated this bid.
: <dfn>bid ad</dfn>
:: The [=interest group ad=] within [=generated bid/interest group=] to display.
: <dfn>modified bid</dfn>
:: Null or a [=bid with currency=]. Being null for top level auction.
The bid value a component auction's `scoreAd()` script returns.
Expand Down Expand Up @@ -3532,6 +3587,11 @@ A <dfn>reporting result</dfn> is a [=struct=] with the following [=struct/items=
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=URLs=], initially null. Set by
{{InterestGroupReportingScriptRunnerGlobalScope/registerAdBeacon(map)}}.

: <dfn>reporting macro map</dfn>
:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are
[=strings=], initially null. Set by
{{InterestGroupReportingScriptRunnerGlobalScope/registerAdMacro(name, value)}}.
</dl>

# Privacy Considerations # {#privacy-considerations}
Expand Down